1//===--- APINotesReader.cpp - API Notes Reader ------------------*- 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 implements the \c APINotesReader class that reads source
10// API notes data providing additional information about source code as
11// a separate input, such as the non-nil/nilable annotations for
12// method parameters.
13//
14//===----------------------------------------------------------------------===//
15#include "clang/APINotes/APINotesReader.h"
16#include "APINotesFormat.h"
17#include "clang/APINotes/Types.h"
18#include "llvm/ADT/Hashing.h"
19#include "llvm/Bitstream/BitstreamReader.h"
20#include "llvm/Support/DJB.h"
21#include "llvm/Support/OnDiskHashTable.h"
22
23namespace clang {
24namespace api_notes {
25using namespace llvm::support;
26
27namespace {
28/// Deserialize a version tuple.
29llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
30 uint8_t NumVersions = (*Data++) & 0x03;
31
32 unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
33 if (NumVersions == 0)
34 return llvm::VersionTuple(Major);
35
36 unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
37 if (NumVersions == 1)
38 return llvm::VersionTuple(Major, Minor);
39
40 unsigned Subminor =
41 endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
42 if (NumVersions == 2)
43 return llvm::VersionTuple(Major, Minor, Subminor);
44
45 unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
46 return llvm::VersionTuple(Major, Minor, Subminor, Build);
47}
48
49static FunctionTableKey readFunctionTableKey(const uint8_t *Data,
50 unsigned Length) {
51 assert(Length >= FunctionTableKeyBaseLength &&
52 "Unexpected function table key length");
53
54 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
55 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
56 uint8_t FunctionKeyFlags =
57 endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
58 auto ParameterCount =
59 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
60
61 assert(Length ==
62 FunctionTableKeyBaseLength + ParameterCount * sizeof(uint32_t) &&
63 "Unexpected function table key length");
64
65 llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs;
66 ParameterTypeIDs.reserve(N: ParameterCount);
67 for (unsigned I = 0; I != ParameterCount; ++I)
68 ParameterTypeIDs.push_back(
69 Elt: endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data));
70
71 assert((FunctionKeyFlags & ~FunctionKeyHasParameterSelector) == 0 &&
72 "Unexpected function table key flags");
73 if (FunctionKeyFlags & FunctionKeyHasParameterSelector)
74 return {CtxID, NameID, ParameterTypeIDs};
75
76 assert(ParameterTypeIDs.empty() &&
77 "Broad function table key should not store parameters");
78 return {CtxID, NameID};
79}
80
81/// An on-disk hash table whose data is versioned based on the Swift version.
82template <typename Derived, typename KeyType, typename UnversionedDataType>
83class VersionedTableInfo {
84public:
85 using internal_key_type = KeyType;
86 using external_key_type = KeyType;
87 using data_type =
88 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
89 using hash_value_type = size_t;
90 using offset_type = unsigned;
91
92 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
93
94 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
95
96 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
97 return LHS == RHS;
98 }
99
100 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
101 unsigned KeyLength =
102 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
103 unsigned DataLength =
104 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
105 return {KeyLength, DataLength};
106 }
107
108 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
109 unsigned Length) {
110 unsigned NumElements =
111 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
112 data_type Result;
113 Result.reserve(NumElements);
114 for (unsigned i = 0; i != NumElements; ++i) {
115 auto version = ReadVersionTuple(Data);
116 const auto *DataBefore = Data;
117 (void)DataBefore;
118 auto UnversionedData = Derived::readUnversioned(Key, Data);
119 assert(Data != DataBefore &&
120 "Unversioned data reader didn't move pointer");
121 Result.push_back({version, UnversionedData});
122 }
123 return Result;
124 }
125};
126
127/// Read serialized CommonEntityInfo.
128void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
129 uint8_t EncodedBits = *Data++;
130 Info.Unavailable = (EncodedBits >> 1) & 0x01;
131 Info.UnavailableInSwift = EncodedBits & 0x01;
132 if ((EncodedBits >> 2) & 0x01)
133 Info.setSwiftPrivate(static_cast<bool>((EncodedBits >> 3) & 0x01));
134 if ((EncodedBits >> 4) & 0x01)
135 Info.setSwiftSafety(
136 static_cast<SwiftSafetyKind>((EncodedBits >> 5) & 0x03));
137
138 unsigned MsgLength =
139 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
140 Info.UnavailableMsg =
141 std::string(reinterpret_cast<const char *>(Data),
142 reinterpret_cast<const char *>(Data) + MsgLength);
143 Data += MsgLength;
144
145 unsigned SwiftNameLength =
146 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
147 Info.SwiftName =
148 std::string(reinterpret_cast<const char *>(Data),
149 reinterpret_cast<const char *>(Data) + SwiftNameLength);
150 Data += SwiftNameLength;
151}
152
153/// Read serialized CommonTypeInfo.
154void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
155 ReadCommonEntityInfo(Data, Info);
156
157 unsigned SwiftBridgeLength =
158 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
159 if (SwiftBridgeLength > 0) {
160 Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data),
161 SwiftBridgeLength - 1));
162 Data += SwiftBridgeLength - 1;
163 }
164
165 unsigned ErrorDomainLength =
166 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
167 if (ErrorDomainLength > 0) {
168 Info.setNSErrorDomain(std::optional<std::string>(std::string(
169 reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
170 Data += ErrorDomainLength - 1;
171 }
172
173 if (unsigned ConformanceLength =
174 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data)) {
175 Info.setSwiftConformance(std::string(reinterpret_cast<const char *>(Data),
176 ConformanceLength - 1));
177 Data += ConformanceLength - 1;
178 }
179}
180
181/// Used to deserialize the on-disk identifier table.
182class IdentifierTableInfo {
183public:
184 using internal_key_type = llvm::StringRef;
185 using external_key_type = llvm::StringRef;
186 using data_type = IdentifierID;
187 using hash_value_type = uint32_t;
188 using offset_type = unsigned;
189
190 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
191
192 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
193
194 hash_value_type ComputeHash(internal_key_type Key) {
195 return llvm::djbHash(Buffer: Key);
196 }
197
198 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
199 return LHS == RHS;
200 }
201
202 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
203 unsigned KeyLength =
204 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
205 unsigned DataLength =
206 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
207 return {KeyLength, DataLength};
208 }
209
210 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
211 return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);
212 }
213
214 static data_type ReadData(internal_key_type key, const uint8_t *Data,
215 unsigned Length) {
216 return endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
217 }
218};
219
220/// Used to deserialize the on-disk table of Objective-C classes and C++
221/// namespaces.
222class ContextIDTableInfo {
223public:
224 using internal_key_type = ContextTableKey;
225 using external_key_type = internal_key_type;
226 using data_type = unsigned;
227 using hash_value_type = size_t;
228 using offset_type = unsigned;
229
230 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
231
232 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
233
234 hash_value_type ComputeHash(internal_key_type Key) {
235 return static_cast<size_t>(Key.hashValue());
236 }
237
238 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
239 return LHS == RHS;
240 }
241
242 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
243 unsigned KeyLength =
244 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
245 unsigned DataLength =
246 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
247 return {KeyLength, DataLength};
248 }
249
250 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
251 auto ParentCtxID =
252 endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
253 auto ContextKind =
254 endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
255 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
256 return {ParentCtxID, ContextKind, NameID};
257 }
258
259 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
260 unsigned Length) {
261 return endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
262 }
263};
264
265/// Used to deserialize the on-disk Objective-C property table.
266class ContextInfoTableInfo
267 : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
268public:
269 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
270 return endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
271 }
272
273 hash_value_type ComputeHash(internal_key_type Key) {
274 return static_cast<size_t>(llvm::hash_value(value: Key));
275 }
276
277 static ContextInfo readUnversioned(internal_key_type Key,
278 const uint8_t *&Data) {
279 ContextInfo Info;
280 ReadCommonTypeInfo(Data, Info);
281 uint8_t Payload = *Data++;
282
283 if (Payload & 0x01)
284 Info.setHasDesignatedInits(true);
285 Payload = Payload >> 1;
286
287 if (Payload & 0x4)
288 Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));
289 Payload >>= 3;
290
291 if (Payload & (1 << 1))
292 Info.setSwiftObjCMembers(Payload & 1);
293 Payload >>= 2;
294
295 if (Payload & (1 << 1))
296 Info.setSwiftImportAsNonGeneric(Payload & 1);
297
298 return Info;
299 }
300};
301
302/// Read serialized VariableInfo.
303void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) {
304 ReadCommonEntityInfo(Data, Info);
305 if (*Data++) {
306 Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data));
307 }
308 ++Data;
309
310 auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
311 Info.setType(std::string(Data, Data + TypeLen));
312 Data += TypeLen;
313}
314
315/// Used to deserialize the on-disk Objective-C property table.
316class ObjCPropertyTableInfo
317 : public VersionedTableInfo<ObjCPropertyTableInfo,
318 std::tuple<uint32_t, uint32_t, uint8_t>,
319 ObjCPropertyInfo> {
320public:
321 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
322 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
323 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
324 char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
325 return {ClassID, NameID, IsInstance};
326 }
327
328 hash_value_type ComputeHash(internal_key_type Key) {
329 return static_cast<size_t>(llvm::hash_value(arg: Key));
330 }
331
332 static ObjCPropertyInfo readUnversioned(internal_key_type Key,
333 const uint8_t *&Data) {
334 ObjCPropertyInfo Info;
335 ReadVariableInfo(Data, Info);
336 uint8_t Flags = *Data++;
337 if (Flags & (1 << 0))
338 Info.setSwiftImportAsAccessors(Flags & (1 << 1));
339 return Info;
340 }
341};
342
343/// Used to deserialize the on-disk C record field table.
344class FieldTableInfo
345 : public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
346public:
347 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
348 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
349 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
350 return {CtxID, NameID};
351 }
352
353 hash_value_type ComputeHash(internal_key_type Key) {
354 return static_cast<size_t>(Key.hashValue());
355 }
356
357 static FieldInfo readUnversioned(internal_key_type Key,
358 const uint8_t *&Data) {
359 FieldInfo Info;
360 ReadVariableInfo(Data, Info);
361 return Info;
362 }
363};
364
365/// Read serialized BoundsSafetyInfo.
366void ReadBoundsSafetyInfo(const uint8_t *&Data, BoundsSafetyInfo &Info) {
367 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
368
369 if (Payload & 0x01) {
370 uint8_t Level = (Payload >> 1) & 0x7;
371 Info.setLevelAudited(Level);
372 }
373 Payload >>= 4;
374
375 if (Payload & 0x01) {
376 uint8_t Kind = (Payload >> 1) & 0x7;
377 assert(Kind <=
378 static_cast<uint8_t>(BoundsSafetyInfo::BoundsSafetyKind::EndedBy));
379 Info.setKindAudited(static_cast<BoundsSafetyInfo::BoundsSafetyKind>(Kind));
380 }
381
382 uint16_t ExternalBoundsLen =
383 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
384 Info.ExternalBounds = std::string(Data, Data + ExternalBoundsLen);
385 Data += ExternalBoundsLen;
386}
387
388/// Read serialized ParamInfo.
389void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
390 ReadVariableInfo(Data, Info);
391
392 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
393 if (auto RawConvention = Payload & 0x7) {
394 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
395 Info.setRetainCountConvention(Convention);
396 }
397 Payload >>= 3;
398 if (Payload & 0x01)
399 Info.setLifetimebound(Payload & 0x02);
400 Payload >>= 2;
401 if (Payload & 0x01)
402 Info.setNoEscape(Payload & 0x02);
403 Payload >>= 2;
404 if (Payload & 0x01)
405 ReadBoundsSafetyInfo(Data, Info&: Info.BoundsSafety.emplace());
406}
407
408/// Read serialized FunctionInfo.
409void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
410 ReadCommonEntityInfo(Data, Info);
411
412 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
413 if (Payload & 0x1)
414 Info.UnsafeBufferUsage = 1;
415 Payload >>= 0x1;
416 if (auto RawConvention = Payload & 0x7) {
417 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
418 Info.setRetainCountConvention(Convention);
419 }
420 Payload >>= 3;
421 Info.NullabilityAudited = Payload & 0x1;
422 Payload >>= 1;
423 assert(Payload == 0 && "Bad API notes");
424
425 Info.NumAdjustedNullable =
426 endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
427 Info.NullabilityPayload =
428 endian::readNext<uint64_t, llvm::endianness::little>(memory&: Data);
429
430 unsigned NumParams =
431 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
432 while (NumParams > 0) {
433 ParamInfo pi;
434 ReadParamInfo(Data, Info&: pi);
435 Info.Params.push_back(x: pi);
436 --NumParams;
437 }
438
439 unsigned ResultTypeLen =
440 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
441 Info.ResultType = std::string(Data, Data + ResultTypeLen);
442 Data += ResultTypeLen;
443
444 unsigned SwiftReturnOwnershipLength =
445 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
446 Info.SwiftReturnOwnership = std::string(reinterpret_cast<const char *>(Data),
447 reinterpret_cast<const char *>(Data) +
448 SwiftReturnOwnershipLength);
449 Data += SwiftReturnOwnershipLength;
450}
451
452/// Used to deserialize the on-disk Objective-C method table.
453class ObjCMethodTableInfo
454 : public VersionedTableInfo<ObjCMethodTableInfo,
455 std::tuple<uint32_t, uint32_t, uint8_t>,
456 ObjCMethodInfo> {
457public:
458 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
459 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
460 auto SelectorID =
461 endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
462 auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
463 return {ClassID, SelectorID, IsInstance};
464 }
465
466 hash_value_type ComputeHash(internal_key_type Key) {
467 return static_cast<size_t>(llvm::hash_value(arg: Key));
468 }
469
470 static ObjCMethodInfo readUnversioned(internal_key_type Key,
471 const uint8_t *&Data) {
472 ObjCMethodInfo Info;
473 uint8_t Payload = *Data++;
474 bool HasSelf = Payload & 0x01;
475 Payload >>= 1;
476 Info.RequiredInit = Payload & 0x01;
477 Payload >>= 1;
478 Info.DesignatedInit = Payload & 0x01;
479 Payload >>= 1;
480 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
481
482 ReadFunctionInfo(Data, Info);
483 if (HasSelf) {
484 Info.Self = ParamInfo{};
485 ReadParamInfo(Data, Info&: *Info.Self);
486 }
487 return Info;
488 }
489};
490
491/// Used to deserialize the on-disk Objective-C selector table.
492class ObjCSelectorTableInfo {
493public:
494 using internal_key_type = StoredObjCSelector;
495 using external_key_type = internal_key_type;
496 using data_type = SelectorID;
497 using hash_value_type = unsigned;
498 using offset_type = unsigned;
499
500 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
501
502 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
503
504 hash_value_type ComputeHash(internal_key_type Key) {
505 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Selector: Key);
506 }
507
508 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
509 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
510 }
511
512 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
513 unsigned KeyLength =
514 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
515 unsigned DataLength =
516 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
517 return {KeyLength, DataLength};
518 }
519
520 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
521 internal_key_type Key;
522 Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
523 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
524 for (unsigned i = 0; i != NumIdents; ++i) {
525 Key.Identifiers.push_back(
526 Elt: endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data));
527 }
528 return Key;
529 }
530
531 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
532 unsigned Length) {
533 return endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
534 }
535};
536
537/// Used to deserialize the on-disk global variable table.
538class GlobalVariableTableInfo
539 : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
540 GlobalVariableInfo> {
541public:
542 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
543 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
544 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
545 return {CtxID, NameID};
546 }
547
548 hash_value_type ComputeHash(internal_key_type Key) {
549 return static_cast<size_t>(Key.hashValue());
550 }
551
552 static GlobalVariableInfo readUnversioned(internal_key_type Key,
553 const uint8_t *&Data) {
554 GlobalVariableInfo Info;
555 ReadVariableInfo(Data, Info);
556 return Info;
557 }
558};
559
560/// Used to deserialize the on-disk global function table.
561class GlobalFunctionTableInfo
562 : public VersionedTableInfo<GlobalFunctionTableInfo, FunctionTableKey,
563 GlobalFunctionInfo> {
564public:
565 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
566 return readFunctionTableKey(Data, Length);
567 }
568
569 hash_value_type ComputeHash(internal_key_type Key) {
570 return static_cast<size_t>(Key.hashValue());
571 }
572
573 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
574 const uint8_t *&Data) {
575 GlobalFunctionInfo Info;
576 ReadFunctionInfo(Data, Info);
577 return Info;
578 }
579};
580
581/// Used to deserialize the on-disk C++ method table.
582class CXXMethodTableInfo
583 : public VersionedTableInfo<CXXMethodTableInfo, FunctionTableKey,
584 CXXMethodInfo> {
585public:
586 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
587 return readFunctionTableKey(Data, Length);
588 }
589
590 hash_value_type ComputeHash(internal_key_type Key) {
591 return static_cast<size_t>(Key.hashValue());
592 }
593
594 static CXXMethodInfo readUnversioned(internal_key_type Key,
595 const uint8_t *&Data) {
596 CXXMethodInfo Info;
597
598 uint8_t Payload = *Data++;
599 bool HasThis = Payload & 0x01;
600 Payload >>= 1;
601 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
602
603 ReadFunctionInfo(Data, Info);
604 if (HasThis) {
605 Info.This = ParamInfo{};
606 ReadParamInfo(Data, Info&: *Info.This);
607 }
608 return Info;
609 }
610};
611
612/// Used to deserialize the on-disk enumerator table.
613class EnumConstantTableInfo
614 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
615 EnumConstantInfo> {
616public:
617 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
618 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
619 return NameID;
620 }
621
622 hash_value_type ComputeHash(internal_key_type Key) {
623 return static_cast<size_t>(llvm::hash_value(value: Key));
624 }
625
626 static EnumConstantInfo readUnversioned(internal_key_type Key,
627 const uint8_t *&Data) {
628 EnumConstantInfo Info;
629 ReadCommonEntityInfo(Data, Info);
630 return Info;
631 }
632};
633
634/// Used to deserialize the on-disk tag table.
635class TagTableInfo
636 : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
637public:
638 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
639 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
640 auto NameID =
641 endian::readNext<IdentifierID, llvm::endianness::little>(memory&: Data);
642 return {CtxID, NameID};
643 }
644
645 hash_value_type ComputeHash(internal_key_type Key) {
646 return static_cast<size_t>(Key.hashValue());
647 }
648
649 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
650 TagInfo Info;
651
652 uint8_t Payload = *Data++;
653 if (Payload & 1)
654 Info.setFlagEnum(Payload & 2);
655 Payload >>= 2;
656 if (Payload > 0)
657 Info.EnumExtensibility =
658 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
659
660 uint8_t Copyable =
661 endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
662 if (Copyable == kSwiftConforms || Copyable == kSwiftDoesNotConform)
663 Info.setSwiftCopyable(std::optional(Copyable == kSwiftConforms));
664 uint8_t Escapable =
665 endian::readNext<uint8_t, llvm::endianness::little>(memory&: Data);
666 if (Escapable == kSwiftConforms || Escapable == kSwiftDoesNotConform)
667 Info.setSwiftEscapable(std::optional(Escapable == kSwiftConforms));
668
669 unsigned ImportAsLength =
670 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
671 if (ImportAsLength > 0) {
672 Info.SwiftImportAs =
673 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
674 Data += ImportAsLength - 1;
675 }
676 unsigned RetainOpLength =
677 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
678 if (RetainOpLength > 0) {
679 Info.SwiftRetainOp =
680 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
681 Data += RetainOpLength - 1;
682 }
683 unsigned ReleaseOpLength =
684 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
685 if (ReleaseOpLength > 0) {
686 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
687 ReleaseOpLength - 1);
688 Data += ReleaseOpLength - 1;
689 }
690 unsigned DefaultOwnershipLength =
691 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
692 if (DefaultOwnershipLength > 0) {
693 Info.SwiftDefaultOwnership = std::string(
694 reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
695 Data += DefaultOwnershipLength - 1;
696 }
697 unsigned DestroyOpLength =
698 endian::readNext<uint16_t, llvm::endianness::little>(memory&: Data);
699 if (DestroyOpLength > 0) {
700 Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
701 DestroyOpLength - 1);
702 Data += DestroyOpLength - 1;
703 }
704
705 ReadCommonTypeInfo(Data, Info);
706 return Info;
707 }
708};
709
710/// Used to deserialize the on-disk typedef table.
711class TypedefTableInfo
712 : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
713 TypedefInfo> {
714public:
715 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
716 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(memory&: Data);
717 auto nameID =
718 endian::readNext<IdentifierID, llvm::endianness::little>(memory&: Data);
719 return {CtxID, nameID};
720 }
721
722 hash_value_type ComputeHash(internal_key_type Key) {
723 return static_cast<size_t>(Key.hashValue());
724 }
725
726 static TypedefInfo readUnversioned(internal_key_type Key,
727 const uint8_t *&Data) {
728 TypedefInfo Info;
729
730 uint8_t Payload = *Data++;
731 if (Payload > 0)
732 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
733
734 ReadCommonTypeInfo(Data, Info);
735 return Info;
736 }
737};
738} // end anonymous namespace
739
740class APINotesReader::Implementation {
741public:
742 /// The input buffer for the API notes data.
743 llvm::MemoryBuffer *InputBuffer;
744
745 /// The Swift version to use for filtering.
746 llvm::VersionTuple SwiftVersion;
747
748 /// The name of the module that we read from the control block.
749 std::string ModuleName;
750
751 // The size and modification time of the source file from
752 // which this API notes file was created, if known.
753 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
754
755 using SerializedIdentifierTable =
756 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
757
758 /// The identifier table.
759 std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
760
761 using SerializedContextIDTable =
762 llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
763
764 /// The Objective-C / C++ context ID table.
765 std::unique_ptr<SerializedContextIDTable> ContextIDTable;
766
767 using SerializedContextInfoTable =
768 llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
769
770 /// The Objective-C context info table.
771 std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
772
773 using SerializedObjCPropertyTable =
774 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
775
776 /// The Objective-C property table.
777 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
778
779 using SerializedFieldTable =
780 llvm::OnDiskIterableChainedHashTable<FieldTableInfo>;
781
782 /// The C record field table.
783 std::unique_ptr<SerializedFieldTable> FieldTable;
784
785 using SerializedObjCMethodTable =
786 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
787
788 /// The Objective-C method table.
789 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
790
791 using SerializedCXXMethodTable =
792 llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
793
794 /// The C++ method table.
795 std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
796
797 using SerializedObjCSelectorTable =
798 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
799
800 /// The Objective-C selector table.
801 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
802
803 using SerializedGlobalVariableTable =
804 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
805
806 /// The global variable table.
807 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
808
809 using SerializedGlobalFunctionTable =
810 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
811
812 /// The global function table.
813 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
814
815 using SerializedEnumConstantTable =
816 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
817
818 /// The enumerator table.
819 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
820
821 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
822
823 /// The tag table.
824 std::unique_ptr<SerializedTagTable> TagTable;
825
826 using SerializedTypedefTable =
827 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
828
829 /// The typedef table.
830 std::unique_ptr<SerializedTypedefTable> TypedefTable;
831
832 /// Retrieve the identifier ID for the given string, or an empty
833 /// optional if the string is unknown.
834 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
835
836 /// Retrieve the selector ID for the given selector, or an empty
837 /// optional if the string is unknown.
838 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
839
840 llvm::Error readControlBlock(llvm::BitstreamCursor &Cursor,
841 llvm::SmallVectorImpl<uint64_t> &Scratch);
842 llvm::Error readIdentifierBlock(llvm::BitstreamCursor &Cursor,
843 llvm::SmallVectorImpl<uint64_t> &Scratch);
844 llvm::Error readContextBlock(llvm::BitstreamCursor &Cursor,
845 llvm::SmallVectorImpl<uint64_t> &Scratch);
846 llvm::Error readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
847 llvm::SmallVectorImpl<uint64_t> &Scratch);
848 llvm::Error readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
849 llvm::SmallVectorImpl<uint64_t> &Scratch);
850 llvm::Error readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
851 llvm::SmallVectorImpl<uint64_t> &Scratch);
852 llvm::Error readFieldBlock(llvm::BitstreamCursor &Cursor,
853 llvm::SmallVectorImpl<uint64_t> &Scratch);
854 llvm::Error readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
855 llvm::SmallVectorImpl<uint64_t> &Scratch);
856 llvm::Error readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
857 llvm::SmallVectorImpl<uint64_t> &Scratch);
858 std::optional<FunctionTableKey> getFunctionKey(uint32_t ParentContextID,
859 llvm::StringRef Name);
860 template <typename ParameterT>
861 std::optional<FunctionTableKey>
862 getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name,
863 llvm::ArrayRef<ParameterT> Parameters);
864 std::optional<FunctionTableKey>
865 getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name);
866 template <typename ParameterT>
867 std::optional<FunctionTableKey>
868 getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name,
869 llvm::ArrayRef<ParameterT> Parameters);
870
871 llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
872 llvm::SmallVectorImpl<uint64_t> &Scratch);
873 llvm::Error readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
874 llvm::SmallVectorImpl<uint64_t> &Scratch);
875 llvm::Error readTagBlock(llvm::BitstreamCursor &Cursor,
876 llvm::SmallVectorImpl<uint64_t> &Scratch);
877 llvm::Error readTypedefBlock(llvm::BitstreamCursor &Cursor,
878 llvm::SmallVectorImpl<uint64_t> &Scratch);
879};
880
881std::optional<IdentifierID>
882APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
883 if (!IdentifierTable)
884 return std::nullopt;
885
886 if (Str.empty())
887 return IdentifierID(0);
888
889 auto Known = IdentifierTable->find(EKey: Str);
890 if (Known == IdentifierTable->end())
891 return std::nullopt;
892
893 return *Known;
894}
895
896std::optional<FunctionTableKey>
897APINotesReader::Implementation::getFunctionKey(uint32_t ParentContextID,
898 llvm::StringRef Name) {
899 return getFunctionKeyImpl(ParentContextID, Name, GetIdentifier: [this](llvm::StringRef S) {
900 return getIdentifier(Str: S);
901 });
902}
903
904template <typename ParameterT>
905std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
906 uint32_t ParentContextID, llvm::StringRef Name,
907 llvm::ArrayRef<ParameterT> Parameters) {
908 return getFunctionKeyImpl(
909 ParentContextID, Name, Parameters,
910 [this](llvm::StringRef S) { return getIdentifier(Str: S); });
911}
912
913std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
914 std::optional<Context> ParentContext, llvm::StringRef Name) {
915 uint32_t ParentContextID =
916 ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
917 return getFunctionKey(ParentContextID, Name);
918}
919
920template <typename ParameterT>
921std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey(
922 std::optional<Context> ParentContext, llvm::StringRef Name,
923 llvm::ArrayRef<ParameterT> Parameters) {
924 uint32_t ParentContextID =
925 ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
926 return getFunctionKey(ParentContextID, Name, Parameters);
927}
928
929std::optional<SelectorID>
930APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
931 if (!ObjCSelectorTable || !IdentifierTable)
932 return std::nullopt;
933
934 // Translate the identifiers.
935 StoredObjCSelector Key;
936 Key.NumArgs = Selector.NumArgs;
937 for (auto Ident : Selector.Identifiers) {
938 if (auto IdentID = getIdentifier(Str: Ident)) {
939 Key.Identifiers.push_back(Elt: *IdentID);
940 } else {
941 return std::nullopt;
942 }
943 }
944
945 auto Known = ObjCSelectorTable->find(EKey: Key);
946 if (Known == ObjCSelectorTable->end())
947 return std::nullopt;
948
949 return *Known;
950}
951
952llvm::Error APINotesReader::Implementation::readControlBlock(
953 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
954 if (Cursor.EnterSubBlock(BlockID: CONTROL_BLOCK_ID))
955 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
956 S: "Failed to enter control block");
957
958 bool SawMetadata = false;
959
960 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
961 if (!MaybeNext)
962 return MaybeNext.takeError();
963
964 llvm::BitstreamEntry Next = MaybeNext.get();
965
966 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
967 if (Next.Kind == llvm::BitstreamEntry::Error)
968 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
969 S: "Malformed bitstream entry");
970
971 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
972 // Unknown metadata sub-block, possibly for use by a future version of the
973 // API notes format.
974 if (Cursor.SkipBlock())
975 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
976 S: "Failed to skip sub-block");
977
978 MaybeNext = Cursor.advance();
979 if (!MaybeNext)
980 return MaybeNext.takeError();
981
982 Next = MaybeNext.get();
983 continue;
984 }
985
986 Scratch.clear();
987 llvm::StringRef BlobData;
988 llvm::Expected<unsigned> MaybeKind =
989 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
990 if (!MaybeKind) {
991 return MaybeKind.takeError();
992 }
993 unsigned Kind = MaybeKind.get();
994
995 switch (Kind) {
996 case control_block::METADATA:
997 // Already saw metadata.
998 if (SawMetadata)
999 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1000 S: "Multiple metadata records found");
1001
1002 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
1003 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1004 S: "Version mismatch in API Notes");
1005
1006 SawMetadata = true;
1007 break;
1008
1009 case control_block::MODULE_NAME:
1010 ModuleName = BlobData.str();
1011 break;
1012
1013 case control_block::MODULE_OPTIONS:
1014 break;
1015
1016 case control_block::SOURCE_FILE:
1017 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
1018 break;
1019
1020 default:
1021 // Unknown metadata record, possibly for use by a future version of the
1022 // module format.
1023 break;
1024 }
1025
1026 MaybeNext = Cursor.advance();
1027 if (!MaybeNext)
1028 return MaybeNext.takeError();
1029
1030 Next = MaybeNext.get();
1031 }
1032
1033 if (!SawMetadata)
1034 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1035 S: "Missing metadata record");
1036
1037 return llvm::Error::success();
1038}
1039
1040llvm::Error APINotesReader::Implementation::readIdentifierBlock(
1041 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1042 if (Cursor.EnterSubBlock(BlockID: IDENTIFIER_BLOCK_ID))
1043 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1044 S: "Failed to enter identifier block");
1045
1046 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1047 if (!MaybeNext)
1048 return MaybeNext.takeError();
1049
1050 llvm::BitstreamEntry Next = MaybeNext.get();
1051
1052 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1053 if (Next.Kind == llvm::BitstreamEntry::Error)
1054 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1055 S: "Malformed bitstream entry");
1056
1057 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1058 // Unknown sub-block, possibly for use by a future version of the
1059 // API notes format.
1060 if (Cursor.SkipBlock())
1061 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1062 S: "Failed to skip sub-block");
1063
1064 MaybeNext = Cursor.advance();
1065 if (!MaybeNext)
1066 return MaybeNext.takeError();
1067
1068 Next = MaybeNext.get();
1069 continue;
1070 }
1071
1072 Scratch.clear();
1073 llvm::StringRef BlobData;
1074 llvm::Expected<unsigned> MaybeKind =
1075 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1076 if (!MaybeKind) {
1077 return MaybeKind.takeError();
1078 }
1079 unsigned Kind = MaybeKind.get();
1080 switch (Kind) {
1081 case identifier_block::IDENTIFIER_DATA: {
1082 // Already saw identifier table.
1083 if (IdentifierTable)
1084 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1085 S: "Multiple identifier records found");
1086
1087 uint32_t tableOffset;
1088 identifier_block::IdentifierDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1089 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1090
1091 IdentifierTable.reset(p: SerializedIdentifierTable::Create(
1092 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1093 break;
1094 }
1095
1096 default:
1097 // Unknown record, possibly for use by a future version of the
1098 // module format.
1099 break;
1100 }
1101
1102 MaybeNext = Cursor.advance();
1103 if (!MaybeNext)
1104 return MaybeNext.takeError();
1105
1106 Next = MaybeNext.get();
1107 }
1108
1109 return llvm::Error::success();
1110}
1111
1112llvm::Error APINotesReader::Implementation::readContextBlock(
1113 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1114 if (Cursor.EnterSubBlock(BlockID: OBJC_CONTEXT_BLOCK_ID))
1115 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1116 S: "Failed to enter Objective-C context block");
1117
1118 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1119 if (!MaybeNext)
1120 return MaybeNext.takeError();
1121
1122 llvm::BitstreamEntry Next = MaybeNext.get();
1123
1124 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1125 if (Next.Kind == llvm::BitstreamEntry::Error)
1126 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1127 S: "Malformed bitstream entry");
1128
1129 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1130 // Unknown sub-block, possibly for use by a future version of the
1131 // API notes format.
1132 if (Cursor.SkipBlock())
1133 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1134 S: "Failed to skip sub-block");
1135
1136 MaybeNext = Cursor.advance();
1137 if (!MaybeNext)
1138 return MaybeNext.takeError();
1139
1140 Next = MaybeNext.get();
1141 continue;
1142 }
1143
1144 Scratch.clear();
1145 llvm::StringRef BlobData;
1146 llvm::Expected<unsigned> MaybeKind =
1147 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1148 if (!MaybeKind) {
1149 return MaybeKind.takeError();
1150 }
1151 unsigned Kind = MaybeKind.get();
1152 switch (Kind) {
1153 case context_block::CONTEXT_ID_DATA: {
1154 // Already saw Objective-C / C++ context ID table.
1155 if (ContextIDTable)
1156 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1157 S: "Multiple context ID records found");
1158
1159 uint32_t tableOffset;
1160 context_block::ContextIDLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1161 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1162
1163 ContextIDTable.reset(p: SerializedContextIDTable::Create(
1164 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1165 break;
1166 }
1167
1168 case context_block::CONTEXT_INFO_DATA: {
1169 // Already saw Objective-C / C++ context info table.
1170 if (ContextInfoTable)
1171 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1172 S: "Multiple context info records found");
1173
1174 uint32_t tableOffset;
1175 context_block::ContextInfoLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1176 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1177
1178 ContextInfoTable.reset(p: SerializedContextInfoTable::Create(
1179 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1180 break;
1181 }
1182
1183 default:
1184 // Unknown record, possibly for use by a future version of the
1185 // module format.
1186 break;
1187 }
1188
1189 MaybeNext = Cursor.advance();
1190 if (!MaybeNext)
1191 return MaybeNext.takeError();
1192
1193 Next = MaybeNext.get();
1194 }
1195
1196 return llvm::Error::success();
1197}
1198
1199llvm::Error APINotesReader::Implementation::readObjCPropertyBlock(
1200 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1201 if (Cursor.EnterSubBlock(BlockID: OBJC_PROPERTY_BLOCK_ID))
1202 return llvm::createStringError(
1203 EC: llvm::inconvertibleErrorCode(),
1204 S: "Failed to enter Objective-C property block");
1205
1206 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1207 if (!MaybeNext)
1208 return MaybeNext.takeError();
1209
1210 llvm::BitstreamEntry Next = MaybeNext.get();
1211
1212 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1213 if (Next.Kind == llvm::BitstreamEntry::Error)
1214 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1215 S: "Malformed bitstream entry");
1216
1217 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1218 // Unknown sub-block, possibly for use by a future version of the
1219 // API notes format.
1220 if (Cursor.SkipBlock())
1221 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1222 S: "Failed to skip sub-block");
1223
1224 MaybeNext = Cursor.advance();
1225 if (!MaybeNext)
1226 return MaybeNext.takeError();
1227
1228 Next = MaybeNext.get();
1229 continue;
1230 }
1231
1232 Scratch.clear();
1233 llvm::StringRef BlobData;
1234 llvm::Expected<unsigned> MaybeKind =
1235 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1236 if (!MaybeKind) {
1237 return MaybeKind.takeError();
1238 }
1239 unsigned Kind = MaybeKind.get();
1240 switch (Kind) {
1241 case objc_property_block::OBJC_PROPERTY_DATA: {
1242 // Already saw Objective-C property table.
1243 if (ObjCPropertyTable)
1244 return llvm::createStringError(
1245 EC: llvm::inconvertibleErrorCode(),
1246 S: "Multiple Objective-C property records found");
1247
1248 uint32_t tableOffset;
1249 objc_property_block::ObjCPropertyDataLayout::readRecord(buffer&: Scratch,
1250 data&: tableOffset);
1251 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1252
1253 ObjCPropertyTable.reset(p: SerializedObjCPropertyTable::Create(
1254 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1255 break;
1256 }
1257
1258 default:
1259 // Unknown record, possibly for use by a future version of the
1260 // module format.
1261 break;
1262 }
1263
1264 MaybeNext = Cursor.advance();
1265 if (!MaybeNext)
1266 return MaybeNext.takeError();
1267
1268 Next = MaybeNext.get();
1269 }
1270
1271 return llvm::Error::success();
1272}
1273
1274llvm::Error APINotesReader::Implementation::readObjCMethodBlock(
1275 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1276 if (Cursor.EnterSubBlock(BlockID: OBJC_METHOD_BLOCK_ID))
1277 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1278 S: "Failed to enter Objective-C method block");
1279
1280 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1281 if (!MaybeNext)
1282 return MaybeNext.takeError();
1283
1284 llvm::BitstreamEntry Next = MaybeNext.get();
1285 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1286 if (Next.Kind == llvm::BitstreamEntry::Error)
1287 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1288 S: "Malformed bitstream entry");
1289
1290 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1291 // Unknown sub-block, possibly for use by a future version of the
1292 // API notes format.
1293 if (Cursor.SkipBlock())
1294 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1295 S: "Failed to skip sub-block");
1296
1297 MaybeNext = Cursor.advance();
1298 if (!MaybeNext)
1299 return MaybeNext.takeError();
1300
1301 Next = MaybeNext.get();
1302 continue;
1303 }
1304
1305 Scratch.clear();
1306 llvm::StringRef BlobData;
1307 llvm::Expected<unsigned> MaybeKind =
1308 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1309 if (!MaybeKind) {
1310 return MaybeKind.takeError();
1311 }
1312 unsigned Kind = MaybeKind.get();
1313 switch (Kind) {
1314 case objc_method_block::OBJC_METHOD_DATA: {
1315 // Already saw Objective-C method table.
1316 if (ObjCMethodTable)
1317 return llvm::createStringError(
1318 EC: llvm::inconvertibleErrorCode(),
1319 S: "Multiple Objective-C method records found");
1320
1321 uint32_t tableOffset;
1322 objc_method_block::ObjCMethodDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1323 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1324
1325 ObjCMethodTable.reset(p: SerializedObjCMethodTable::Create(
1326 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1327 break;
1328 }
1329
1330 default:
1331 // Unknown record, possibly for use by a future version of the
1332 // module format.
1333 break;
1334 }
1335
1336 MaybeNext = Cursor.advance();
1337 if (!MaybeNext)
1338 return MaybeNext.takeError();
1339
1340 Next = MaybeNext.get();
1341 }
1342
1343 return llvm::Error::success();
1344}
1345
1346llvm::Error APINotesReader::Implementation::readCXXMethodBlock(
1347 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1348 if (Cursor.EnterSubBlock(BlockID: CXX_METHOD_BLOCK_ID))
1349 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1350 S: "Failed to enter C++ method block");
1351
1352 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1353 if (!MaybeNext)
1354 return MaybeNext.takeError();
1355
1356 llvm::BitstreamEntry Next = MaybeNext.get();
1357 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1358 if (Next.Kind == llvm::BitstreamEntry::Error)
1359 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1360 S: "Malformed bitstream entry");
1361
1362 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1363 // Unknown sub-block, possibly for use by a future version of the
1364 // API notes format.
1365 if (Cursor.SkipBlock())
1366 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1367 S: "Failed to skip sub-block");
1368
1369 MaybeNext = Cursor.advance();
1370 if (!MaybeNext)
1371 return MaybeNext.takeError();
1372
1373 Next = MaybeNext.get();
1374 continue;
1375 }
1376
1377 Scratch.clear();
1378 llvm::StringRef BlobData;
1379 llvm::Expected<unsigned> MaybeKind =
1380 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1381 if (!MaybeKind) {
1382 return MaybeKind.takeError();
1383 }
1384 unsigned Kind = MaybeKind.get();
1385 switch (Kind) {
1386 case cxx_method_block::CXX_METHOD_DATA: {
1387 // Already saw C++ method table.
1388 if (CXXMethodTable)
1389 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1390 S: "Multiple C++ method records found");
1391
1392 uint32_t tableOffset;
1393 cxx_method_block::CXXMethodDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1394 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1395
1396 CXXMethodTable.reset(p: SerializedCXXMethodTable::Create(
1397 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1398 break;
1399 }
1400
1401 default:
1402 // Unknown record, possibly for use by a future version of the
1403 // module format.
1404 break;
1405 }
1406
1407 MaybeNext = Cursor.advance();
1408 if (!MaybeNext)
1409 return MaybeNext.takeError();
1410
1411 Next = MaybeNext.get();
1412 }
1413
1414 return llvm::Error::success();
1415}
1416
1417llvm::Error APINotesReader::Implementation::readFieldBlock(
1418 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1419 if (Cursor.EnterSubBlock(BlockID: FIELD_BLOCK_ID))
1420 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1421 S: "Failed to enter field block");
1422
1423 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1424 if (!MaybeNext)
1425 return MaybeNext.takeError();
1426
1427 llvm::BitstreamEntry Next = MaybeNext.get();
1428 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1429 if (Next.Kind == llvm::BitstreamEntry::Error)
1430 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1431 S: "Malformed bitstream entry");
1432
1433 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1434 // Unknown sub-block, possibly for use by a future version of the
1435 // API notes format.
1436 if (Cursor.SkipBlock())
1437 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1438 S: "Failed to skip sub-block");
1439
1440 MaybeNext = Cursor.advance();
1441 if (!MaybeNext)
1442 return MaybeNext.takeError();
1443
1444 Next = MaybeNext.get();
1445 continue;
1446 }
1447
1448 Scratch.clear();
1449 llvm::StringRef BlobData;
1450 llvm::Expected<unsigned> MaybeKind =
1451 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1452 if (!MaybeKind) {
1453 return MaybeKind.takeError();
1454 }
1455 unsigned Kind = MaybeKind.get();
1456 switch (Kind) {
1457 case field_block::FIELD_DATA: {
1458 // Already saw field table.
1459 if (FieldTable)
1460 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1461 S: "Multiple field records found");
1462
1463 uint32_t tableOffset;
1464 field_block::FieldDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1465 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1466
1467 FieldTable.reset(p: SerializedFieldTable::Create(
1468 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1469 break;
1470 }
1471
1472 default:
1473 // Unknown record, possibly for use by a future version of the
1474 // module format.
1475 break;
1476 }
1477
1478 MaybeNext = Cursor.advance();
1479 if (!MaybeNext)
1480 return MaybeNext.takeError();
1481
1482 Next = MaybeNext.get();
1483 }
1484
1485 return llvm::Error::success();
1486}
1487
1488llvm::Error APINotesReader::Implementation::readObjCSelectorBlock(
1489 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1490 if (Cursor.EnterSubBlock(BlockID: OBJC_SELECTOR_BLOCK_ID))
1491 return llvm::createStringError(
1492 EC: llvm::inconvertibleErrorCode(),
1493 S: "Failed to enter Objective-C selector block");
1494
1495 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1496 if (!MaybeNext)
1497 return MaybeNext.takeError();
1498
1499 llvm::BitstreamEntry Next = MaybeNext.get();
1500 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1501 if (Next.Kind == llvm::BitstreamEntry::Error)
1502 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1503 S: "Malformed bitstream entry");
1504
1505 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1506 // Unknown sub-block, possibly for use by a future version of the
1507 // API notes format.
1508 if (Cursor.SkipBlock())
1509 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1510 S: "Failed to skip sub-block");
1511
1512 MaybeNext = Cursor.advance();
1513 if (!MaybeNext)
1514 return MaybeNext.takeError();
1515
1516 Next = MaybeNext.get();
1517 continue;
1518 }
1519
1520 Scratch.clear();
1521 llvm::StringRef BlobData;
1522 llvm::Expected<unsigned> MaybeKind =
1523 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1524 if (!MaybeKind) {
1525 return MaybeKind.takeError();
1526 }
1527 unsigned Kind = MaybeKind.get();
1528 switch (Kind) {
1529 case objc_selector_block::OBJC_SELECTOR_DATA: {
1530 // Already saw Objective-C selector table.
1531 if (ObjCSelectorTable)
1532 return llvm::createStringError(
1533 EC: llvm::inconvertibleErrorCode(),
1534 S: "Multiple Objective-C selector records found");
1535
1536 uint32_t tableOffset;
1537 objc_selector_block::ObjCSelectorDataLayout::readRecord(buffer&: Scratch,
1538 data&: tableOffset);
1539 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1540
1541 ObjCSelectorTable.reset(p: SerializedObjCSelectorTable::Create(
1542 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1543 break;
1544 }
1545
1546 default:
1547 // Unknown record, possibly for use by a future version of the
1548 // module format.
1549 break;
1550 }
1551
1552 MaybeNext = Cursor.advance();
1553 if (!MaybeNext)
1554 return MaybeNext.takeError();
1555
1556 Next = MaybeNext.get();
1557 }
1558
1559 return llvm::Error::success();
1560}
1561
1562llvm::Error APINotesReader::Implementation::readGlobalVariableBlock(
1563 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1564 if (Cursor.EnterSubBlock(BlockID: GLOBAL_VARIABLE_BLOCK_ID))
1565 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1566 S: "Failed to enter global variable block");
1567
1568 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1569 if (!MaybeNext)
1570 return MaybeNext.takeError();
1571
1572 llvm::BitstreamEntry Next = MaybeNext.get();
1573 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1574 if (Next.Kind == llvm::BitstreamEntry::Error)
1575 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1576 S: "Malformed bitstream entry");
1577
1578 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1579 // Unknown sub-block, possibly for use by a future version of the
1580 // API notes format.
1581 if (Cursor.SkipBlock())
1582 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1583 S: "Failed to skip sub-block");
1584
1585 MaybeNext = Cursor.advance();
1586 if (!MaybeNext)
1587 return MaybeNext.takeError();
1588
1589 Next = MaybeNext.get();
1590 continue;
1591 }
1592
1593 Scratch.clear();
1594 llvm::StringRef BlobData;
1595 llvm::Expected<unsigned> MaybeKind =
1596 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1597 if (!MaybeKind) {
1598 return MaybeKind.takeError();
1599 }
1600 unsigned Kind = MaybeKind.get();
1601 switch (Kind) {
1602 case global_variable_block::GLOBAL_VARIABLE_DATA: {
1603 // Already saw global variable table.
1604 if (GlobalVariableTable)
1605 return llvm::createStringError(
1606 EC: llvm::inconvertibleErrorCode(),
1607 S: "Multiple global variable records found");
1608
1609 uint32_t tableOffset;
1610 global_variable_block::GlobalVariableDataLayout::readRecord(buffer&: Scratch,
1611 data&: tableOffset);
1612 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1613
1614 GlobalVariableTable.reset(p: SerializedGlobalVariableTable::Create(
1615 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1616 break;
1617 }
1618
1619 default:
1620 // Unknown record, possibly for use by a future version of the
1621 // module format.
1622 break;
1623 }
1624
1625 MaybeNext = Cursor.advance();
1626 if (!MaybeNext)
1627 return MaybeNext.takeError();
1628
1629 Next = MaybeNext.get();
1630 }
1631
1632 return llvm::Error::success();
1633}
1634
1635llvm::Error APINotesReader::Implementation::readGlobalFunctionBlock(
1636 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1637 if (Cursor.EnterSubBlock(BlockID: GLOBAL_FUNCTION_BLOCK_ID))
1638 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1639 S: "Failed to enter global function block");
1640
1641 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1642 if (!MaybeNext)
1643 return MaybeNext.takeError();
1644
1645 llvm::BitstreamEntry Next = MaybeNext.get();
1646 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1647 if (Next.Kind == llvm::BitstreamEntry::Error)
1648 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1649 S: "Malformed bitstream entry");
1650
1651 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1652 // Unknown sub-block, possibly for use by a future version of the
1653 // API notes format.
1654 if (Cursor.SkipBlock())
1655 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1656 S: "Failed to skip sub-block");
1657
1658 MaybeNext = Cursor.advance();
1659 if (!MaybeNext)
1660 return MaybeNext.takeError();
1661
1662 Next = MaybeNext.get();
1663 continue;
1664 }
1665
1666 Scratch.clear();
1667 llvm::StringRef BlobData;
1668 llvm::Expected<unsigned> MaybeKind =
1669 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1670 if (!MaybeKind) {
1671 return MaybeKind.takeError();
1672 }
1673 unsigned Kind = MaybeKind.get();
1674 switch (Kind) {
1675 case global_function_block::GLOBAL_FUNCTION_DATA: {
1676 // Already saw global function table.
1677 if (GlobalFunctionTable)
1678 return llvm::createStringError(
1679 EC: llvm::inconvertibleErrorCode(),
1680 S: "Multiple global function records found");
1681
1682 uint32_t tableOffset;
1683 global_function_block::GlobalFunctionDataLayout::readRecord(buffer&: Scratch,
1684 data&: tableOffset);
1685 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1686
1687 GlobalFunctionTable.reset(p: SerializedGlobalFunctionTable::Create(
1688 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1689 break;
1690 }
1691
1692 default:
1693 // Unknown record, possibly for use by a future version of the
1694 // module format.
1695 break;
1696 }
1697
1698 MaybeNext = Cursor.advance();
1699 if (!MaybeNext)
1700 return MaybeNext.takeError();
1701
1702 Next = MaybeNext.get();
1703 }
1704
1705 return llvm::Error::success();
1706}
1707
1708llvm::Error APINotesReader::Implementation::readEnumConstantBlock(
1709 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1710 if (Cursor.EnterSubBlock(BlockID: ENUM_CONSTANT_BLOCK_ID))
1711 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1712 S: "Failed to enter enum constant block");
1713
1714 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1715 if (!MaybeNext)
1716 return MaybeNext.takeError();
1717
1718 llvm::BitstreamEntry Next = MaybeNext.get();
1719 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1720 if (Next.Kind == llvm::BitstreamEntry::Error)
1721 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1722 S: "Malformed bitstream entry");
1723
1724 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1725 // Unknown sub-block, possibly for use by a future version of the
1726 // API notes format.
1727 if (Cursor.SkipBlock())
1728 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1729 S: "Failed to skip sub-block");
1730
1731 MaybeNext = Cursor.advance();
1732 if (!MaybeNext)
1733 return MaybeNext.takeError();
1734
1735 Next = MaybeNext.get();
1736 continue;
1737 }
1738
1739 Scratch.clear();
1740 llvm::StringRef BlobData;
1741 llvm::Expected<unsigned> MaybeKind =
1742 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1743 if (!MaybeKind) {
1744 return MaybeKind.takeError();
1745 }
1746 unsigned Kind = MaybeKind.get();
1747 switch (Kind) {
1748 case enum_constant_block::ENUM_CONSTANT_DATA: {
1749 // Already saw enumerator table.
1750 if (EnumConstantTable)
1751 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1752 S: "Multiple enum constant records found");
1753
1754 uint32_t tableOffset;
1755 enum_constant_block::EnumConstantDataLayout::readRecord(buffer&: Scratch,
1756 data&: tableOffset);
1757 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1758
1759 EnumConstantTable.reset(p: SerializedEnumConstantTable::Create(
1760 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1761 break;
1762 }
1763
1764 default:
1765 // Unknown record, possibly for use by a future version of the
1766 // module format.
1767 break;
1768 }
1769
1770 MaybeNext = Cursor.advance();
1771 if (!MaybeNext)
1772 return MaybeNext.takeError();
1773
1774 Next = MaybeNext.get();
1775 }
1776
1777 return llvm::Error::success();
1778}
1779
1780llvm::Error APINotesReader::Implementation::readTagBlock(
1781 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1782 if (Cursor.EnterSubBlock(BlockID: TAG_BLOCK_ID))
1783 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1784 S: "Failed to enter tag block");
1785
1786 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1787 if (!MaybeNext)
1788 return MaybeNext.takeError();
1789
1790 llvm::BitstreamEntry Next = MaybeNext.get();
1791 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1792 if (Next.Kind == llvm::BitstreamEntry::Error)
1793 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1794 S: "Malformed bitstream entry");
1795
1796 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1797 // Unknown sub-block, possibly for use by a future version of the
1798 // API notes format.
1799 if (Cursor.SkipBlock())
1800 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1801 S: "Failed to skip sub-block");
1802
1803 MaybeNext = Cursor.advance();
1804 if (!MaybeNext)
1805 return MaybeNext.takeError();
1806
1807 Next = MaybeNext.get();
1808 continue;
1809 }
1810
1811 Scratch.clear();
1812 llvm::StringRef BlobData;
1813 llvm::Expected<unsigned> MaybeKind =
1814 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1815 if (!MaybeKind) {
1816 return MaybeKind.takeError();
1817 }
1818 unsigned Kind = MaybeKind.get();
1819 switch (Kind) {
1820 case tag_block::TAG_DATA: {
1821 // Already saw tag table.
1822 if (TagTable)
1823 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1824 S: "Multiple tag records found");
1825
1826 uint32_t tableOffset;
1827 tag_block::TagDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1828 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1829
1830 TagTable.reset(p: SerializedTagTable::Create(Buckets: base + tableOffset,
1831 Payload: base + sizeof(uint32_t), Base: base));
1832 break;
1833 }
1834
1835 default:
1836 // Unknown record, possibly for use by a future version of the
1837 // module format.
1838 break;
1839 }
1840
1841 MaybeNext = Cursor.advance();
1842 if (!MaybeNext)
1843 return MaybeNext.takeError();
1844
1845 Next = MaybeNext.get();
1846 }
1847
1848 return llvm::Error::success();
1849}
1850
1851llvm::Error APINotesReader::Implementation::readTypedefBlock(
1852 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1853 if (Cursor.EnterSubBlock(BlockID: TYPEDEF_BLOCK_ID))
1854 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1855 S: "Failed to enter typedef block");
1856
1857 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1858 if (!MaybeNext)
1859 return MaybeNext.takeError();
1860
1861 llvm::BitstreamEntry Next = MaybeNext.get();
1862 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1863 if (Next.Kind == llvm::BitstreamEntry::Error)
1864 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1865 S: "Malformed bitstream entry");
1866
1867 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1868 // Unknown sub-block, possibly for use by a future version of the
1869 // API notes format.
1870 if (Cursor.SkipBlock())
1871 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1872 S: "Failed to skip sub-block");
1873
1874 MaybeNext = Cursor.advance();
1875 if (!MaybeNext)
1876 return MaybeNext.takeError();
1877
1878 Next = MaybeNext.get();
1879 continue;
1880 }
1881
1882 Scratch.clear();
1883 llvm::StringRef BlobData;
1884 llvm::Expected<unsigned> MaybeKind =
1885 Cursor.readRecord(AbbrevID: Next.ID, Vals&: Scratch, Blob: &BlobData);
1886 if (!MaybeKind) {
1887 return MaybeKind.takeError();
1888 }
1889 unsigned Kind = MaybeKind.get();
1890 switch (Kind) {
1891 case typedef_block::TYPEDEF_DATA: {
1892 // Already saw typedef table.
1893 if (TypedefTable)
1894 return llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1895 S: "Multiple typedef records found");
1896
1897 uint32_t tableOffset;
1898 typedef_block::TypedefDataLayout::readRecord(buffer&: Scratch, data&: tableOffset);
1899 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1900
1901 TypedefTable.reset(p: SerializedTypedefTable::Create(
1902 Buckets: base + tableOffset, Payload: base + sizeof(uint32_t), Base: base));
1903 break;
1904 }
1905
1906 default:
1907 // Unknown record, possibly for use by a future version of the
1908 // module format.
1909 break;
1910 }
1911
1912 MaybeNext = Cursor.advance();
1913 if (!MaybeNext)
1914 return MaybeNext.takeError();
1915
1916 Next = MaybeNext.get();
1917 }
1918
1919 return llvm::Error::success();
1920}
1921
1922APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1923 llvm::VersionTuple SwiftVersion,
1924 llvm::Error &Err)
1925 : Implementation(new class Implementation) {
1926
1927 // Initialize the input buffer.
1928 Implementation->InputBuffer = InputBuffer;
1929 Implementation->SwiftVersion = SwiftVersion;
1930 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1931
1932 // Validate signature.
1933 for (auto byte : API_NOTES_SIGNATURE) {
1934 if (Cursor.AtEndOfStream()) {
1935 Err = llvm::createStringError(
1936 EC: llvm::inconvertibleErrorCode(),
1937 S: "Unexpected end of stream while reading signature");
1938 return;
1939 }
1940 llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
1941 Cursor.Read(NumBits: 8);
1942 if (!maybeRead) {
1943 Err = maybeRead.takeError();
1944 return;
1945 }
1946 if (maybeRead.get() != byte) {
1947 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1948 S: "Invalid signature in API notes file");
1949 return;
1950 }
1951 }
1952
1953 // Look at all of the blocks.
1954 bool HasValidControlBlock = false;
1955 llvm::SmallVector<uint64_t, 64> Scratch;
1956 while (!Cursor.AtEndOfStream()) {
1957 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1958 if (!MaybeTopLevelEntry) {
1959 Err = MaybeTopLevelEntry.takeError();
1960 return;
1961 }
1962 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1963
1964 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1965 break;
1966
1967 switch (TopLevelEntry.ID) {
1968 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1969 if (!Cursor.ReadBlockInfoBlock()) {
1970 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1971 S: "Failed to read block info");
1972 return;
1973 }
1974 break;
1975
1976 case CONTROL_BLOCK_ID:
1977 // Only allow a single control block.
1978 if (HasValidControlBlock) {
1979 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1980 S: "Multiple control blocks found");
1981 return;
1982 }
1983 if (llvm::Error BlockErr =
1984 Implementation->readControlBlock(Cursor, Scratch)) {
1985 Err = std::move(BlockErr);
1986 return;
1987 }
1988 HasValidControlBlock = true;
1989 break;
1990
1991 case IDENTIFIER_BLOCK_ID:
1992 if (!HasValidControlBlock) {
1993 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
1994 S: "Missing control block");
1995 return;
1996 }
1997 if (llvm::Error BlockErr =
1998 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1999 Err = std::move(BlockErr);
2000 return;
2001 }
2002 break;
2003
2004 case OBJC_CONTEXT_BLOCK_ID:
2005 if (!HasValidControlBlock) {
2006 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2007 S: "Missing control block");
2008 return;
2009 }
2010 if (llvm::Error BlockErr =
2011 Implementation->readContextBlock(Cursor, Scratch)) {
2012 Err = std::move(BlockErr);
2013 return;
2014 }
2015 break;
2016
2017 case OBJC_PROPERTY_BLOCK_ID:
2018 if (!HasValidControlBlock) {
2019 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2020 S: "Missing control block");
2021 return;
2022 }
2023 if (llvm::Error BlockErr =
2024 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
2025 Err = std::move(BlockErr);
2026 return;
2027 }
2028 break;
2029
2030 case OBJC_METHOD_BLOCK_ID:
2031 if (!HasValidControlBlock) {
2032 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2033 S: "Missing control block");
2034 return;
2035 }
2036 if (llvm::Error BlockErr =
2037 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
2038 Err = std::move(BlockErr);
2039 return;
2040 }
2041 break;
2042
2043 case CXX_METHOD_BLOCK_ID:
2044 if (!HasValidControlBlock) {
2045 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2046 S: "Missing control block");
2047 return;
2048 }
2049 if (llvm::Error BlockErr =
2050 Implementation->readCXXMethodBlock(Cursor, Scratch)) {
2051 Err = std::move(BlockErr);
2052 return;
2053 }
2054 break;
2055
2056 case FIELD_BLOCK_ID:
2057 if (!HasValidControlBlock) {
2058 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2059 S: "Missing control block");
2060 return;
2061 }
2062 if (llvm::Error BlockErr =
2063 Implementation->readFieldBlock(Cursor, Scratch)) {
2064 Err = std::move(BlockErr);
2065 return;
2066 }
2067 break;
2068
2069 case OBJC_SELECTOR_BLOCK_ID:
2070 if (!HasValidControlBlock) {
2071 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2072 S: "Missing control block");
2073 return;
2074 }
2075 if (llvm::Error BlockErr =
2076 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
2077 Err = std::move(BlockErr);
2078 return;
2079 }
2080 break;
2081
2082 case GLOBAL_VARIABLE_BLOCK_ID:
2083 if (!HasValidControlBlock) {
2084 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2085 S: "Missing control block");
2086 return;
2087 }
2088 if (llvm::Error BlockErr =
2089 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
2090 Err = std::move(BlockErr);
2091 return;
2092 }
2093 break;
2094
2095 case GLOBAL_FUNCTION_BLOCK_ID:
2096 if (!HasValidControlBlock) {
2097 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2098 S: "Missing control block");
2099 return;
2100 }
2101 if (llvm::Error BlockErr =
2102 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
2103 Err = std::move(BlockErr);
2104 return;
2105 }
2106 break;
2107
2108 case ENUM_CONSTANT_BLOCK_ID:
2109 if (!HasValidControlBlock) {
2110 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2111 S: "Missing control block");
2112 return;
2113 }
2114 if (llvm::Error BlockErr =
2115 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
2116 Err = std::move(BlockErr);
2117 return;
2118 }
2119 break;
2120
2121 case TAG_BLOCK_ID:
2122 if (!HasValidControlBlock) {
2123 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2124 S: "Missing control block");
2125 return;
2126 }
2127 if (llvm::Error BlockErr =
2128 Implementation->readTagBlock(Cursor, Scratch)) {
2129 Err = std::move(BlockErr);
2130 return;
2131 }
2132 break;
2133
2134 case TYPEDEF_BLOCK_ID:
2135 if (!HasValidControlBlock) {
2136 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2137 S: "Missing control block");
2138 return;
2139 }
2140 if (llvm::Error BlockErr =
2141 Implementation->readTypedefBlock(Cursor, Scratch)) {
2142 Err = std::move(BlockErr);
2143 return;
2144 }
2145 break;
2146
2147 default:
2148 // Unknown top-level block, possibly for use by a future version of the
2149 // module format.
2150 if (Cursor.SkipBlock()) {
2151 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2152 S: "Failed to skip unknown top-level block");
2153 return;
2154 }
2155 break;
2156 }
2157 }
2158
2159 if (!Cursor.AtEndOfStream()) {
2160 Err = llvm::createStringError(EC: llvm::inconvertibleErrorCode(),
2161 S: "Bitstream has unread data after all blocks");
2162 return;
2163 }
2164}
2165
2166APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }
2167
2168llvm::Expected<std::unique_ptr<APINotesReader>>
2169APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
2170 llvm::VersionTuple SwiftVersion) {
2171 llvm::Error Err = llvm::Error::success();
2172 std::unique_ptr<APINotesReader> Reader(
2173 new APINotesReader(InputBuffer.release(), SwiftVersion, Err));
2174
2175 if (Err)
2176 return Err;
2177
2178 return std::move(Reader);
2179}
2180
2181template <typename T>
2182APINotesReader::VersionedInfo<T>::VersionedInfo(
2183 llvm::VersionTuple Version,
2184 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
2185 : Results(std::move(R)) {
2186
2187 assert(!Results.empty());
2188 assert(llvm::is_sorted(
2189 Results,
2190 [](const std::pair<llvm::VersionTuple, T> &left,
2191 const std::pair<llvm::VersionTuple, T> &right) -> bool {
2192 // The comparison function should be reflective, and with expensive
2193 // checks we can get callbacks basically checking that lambda(a,a) is
2194 // false. We could still check that we do not find equal elements when
2195 // left!=right.
2196 assert((&left == &right || left.first != right.first) &&
2197 "two entries for the same version");
2198 return left.first < right.first;
2199 }));
2200
2201 Selected = std::nullopt;
2202 for (unsigned i = 0, n = Results.size(); i != n; ++i) {
2203 if (!Version.empty() && Results[i].first >= Version) {
2204 // If the current version is "4", then entries for 4 are better than
2205 // entries for 5, but both are valid. Because entries are sorted, we get
2206 // that behavior by picking the first match.
2207 Selected = i;
2208 break;
2209 }
2210 }
2211
2212 // If we didn't find a match but we have an unversioned result, use the
2213 // unversioned result. This will always be the first entry because we encode
2214 // it as version 0.
2215 if (!Selected && Results[0].first.empty())
2216 Selected = 0;
2217}
2218
2219auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
2220 -> std::optional<ContextID> {
2221 if (!Implementation->ContextIDTable)
2222 return std::nullopt;
2223
2224 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Str: Name);
2225 if (!ClassID)
2226 return std::nullopt;
2227
2228 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2229 // context.
2230 auto KnownID = Implementation->ContextIDTable->find(
2231 EKey: ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
2232 if (KnownID == Implementation->ContextIDTable->end())
2233 return std::nullopt;
2234
2235 return ContextID(*KnownID);
2236}
2237
2238auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
2239 -> VersionedInfo<ContextInfo> {
2240 if (!Implementation->ContextInfoTable)
2241 return std::nullopt;
2242
2243 std::optional<ContextID> CtxID = lookupObjCClassID(Name);
2244 if (!CtxID)
2245 return std::nullopt;
2246
2247 auto KnownInfo = Implementation->ContextInfoTable->find(EKey: CtxID->Value);
2248 if (KnownInfo == Implementation->ContextInfoTable->end())
2249 return std::nullopt;
2250
2251 return {Implementation->SwiftVersion, *KnownInfo};
2252}
2253
2254auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
2255 -> std::optional<ContextID> {
2256 if (!Implementation->ContextIDTable)
2257 return std::nullopt;
2258
2259 std::optional<IdentifierID> classID = Implementation->getIdentifier(Str: Name);
2260 if (!classID)
2261 return std::nullopt;
2262
2263 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2264 // context.
2265 auto KnownID = Implementation->ContextIDTable->find(
2266 EKey: ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
2267 if (KnownID == Implementation->ContextIDTable->end())
2268 return std::nullopt;
2269
2270 return ContextID(*KnownID);
2271}
2272
2273auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
2274 -> VersionedInfo<ContextInfo> {
2275 if (!Implementation->ContextInfoTable)
2276 return std::nullopt;
2277
2278 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
2279 if (!CtxID)
2280 return std::nullopt;
2281
2282 auto KnownInfo = Implementation->ContextInfoTable->find(EKey: CtxID->Value);
2283 if (KnownInfo == Implementation->ContextInfoTable->end())
2284 return std::nullopt;
2285
2286 return {Implementation->SwiftVersion, *KnownInfo};
2287}
2288
2289auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
2290 bool IsInstance)
2291 -> VersionedInfo<ObjCPropertyInfo> {
2292 if (!Implementation->ObjCPropertyTable)
2293 return std::nullopt;
2294
2295 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Str: Name);
2296 if (!PropertyID)
2297 return std::nullopt;
2298
2299 auto Known = Implementation->ObjCPropertyTable->find(
2300 EKey: std::make_tuple(args&: CtxID.Value, args&: *PropertyID, args: (char)IsInstance));
2301 if (Known == Implementation->ObjCPropertyTable->end())
2302 return std::nullopt;
2303
2304 return {Implementation->SwiftVersion, *Known};
2305}
2306
2307auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
2308 bool IsInstanceMethod)
2309 -> VersionedInfo<ObjCMethodInfo> {
2310 if (!Implementation->ObjCMethodTable)
2311 return std::nullopt;
2312
2313 std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
2314 if (!SelID)
2315 return std::nullopt;
2316
2317 auto Known = Implementation->ObjCMethodTable->find(
2318 EKey: ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
2319 IsInstanceMethod});
2320 if (Known == Implementation->ObjCMethodTable->end())
2321 return std::nullopt;
2322
2323 return {Implementation->SwiftVersion, *Known};
2324}
2325
2326auto APINotesReader::lookupField(ContextID CtxID, llvm::StringRef Name)
2327 -> VersionedInfo<FieldInfo> {
2328 if (!Implementation->FieldTable)
2329 return std::nullopt;
2330
2331 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Str: Name);
2332 if (!NameID)
2333 return std::nullopt;
2334
2335 auto Known = Implementation->FieldTable->find(
2336 EKey: SingleDeclTableKey(CtxID.Value, *NameID));
2337 if (Known == Implementation->FieldTable->end())
2338 return std::nullopt;
2339
2340 return {Implementation->SwiftVersion, *Known};
2341}
2342
2343auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2344 -> VersionedInfo<CXXMethodInfo> {
2345 return lookupCXXMethodImpl(CtxID, Name);
2346}
2347
2348auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name,
2349 llvm::ArrayRef<std::string> Parameters)
2350 -> VersionedInfo<CXXMethodInfo> {
2351 return lookupCXXMethodImpl(CtxID, Name, Parameters);
2352}
2353
2354auto APINotesReader::lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name)
2355 -> VersionedInfo<CXXMethodInfo> {
2356 if (!Implementation->CXXMethodTable)
2357 return std::nullopt;
2358
2359 std::optional<FunctionTableKey> Key =
2360 Implementation->getFunctionKey(ParentContextID: CtxID.Value, Name);
2361 if (!Key)
2362 return std::nullopt;
2363
2364 auto Known = Implementation->CXXMethodTable->find(EKey: *Key);
2365 if (Known == Implementation->CXXMethodTable->end())
2366 return std::nullopt;
2367
2368 return {Implementation->SwiftVersion, *Known};
2369}
2370
2371template <typename ParameterT>
2372auto APINotesReader::lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name,
2373 llvm::ArrayRef<ParameterT> Parameters)
2374 -> VersionedInfo<CXXMethodInfo> {
2375 if (!Implementation->CXXMethodTable)
2376 return std::nullopt;
2377
2378 std::optional<FunctionTableKey> Key =
2379 Implementation->getFunctionKey(CtxID.Value, Name, Parameters);
2380 if (!Key)
2381 return std::nullopt;
2382
2383 auto Known = Implementation->CXXMethodTable->find(EKey: *Key);
2384 if (Known == Implementation->CXXMethodTable->end())
2385 return std::nullopt;
2386
2387 return {Implementation->SwiftVersion, *Known};
2388}
2389
2390auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
2391 std::optional<Context> Ctx)
2392 -> VersionedInfo<GlobalVariableInfo> {
2393 if (!Implementation->GlobalVariableTable)
2394 return std::nullopt;
2395
2396 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Str: Name);
2397 if (!NameID)
2398 return std::nullopt;
2399
2400 SingleDeclTableKey Key(Ctx, *NameID);
2401
2402 auto Known = Implementation->GlobalVariableTable->find(EKey: Key);
2403 if (Known == Implementation->GlobalVariableTable->end())
2404 return std::nullopt;
2405
2406 return {Implementation->SwiftVersion, *Known};
2407}
2408
2409auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
2410 std::optional<Context> Ctx)
2411 -> VersionedInfo<GlobalFunctionInfo> {
2412 return lookupGlobalFunctionImpl(Name, Ctx);
2413}
2414
2415auto APINotesReader::lookupGlobalFunction(
2416 llvm::StringRef Name, llvm::ArrayRef<std::string> Parameters,
2417 std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
2418 return lookupGlobalFunctionImpl(Name, Parameters, Ctx);
2419}
2420
2421auto APINotesReader::lookupGlobalFunctionImpl(llvm::StringRef Name,
2422 std::optional<Context> Ctx)
2423 -> VersionedInfo<GlobalFunctionInfo> {
2424 if (!Implementation->GlobalFunctionTable)
2425 return std::nullopt;
2426
2427 std::optional<FunctionTableKey> Key =
2428 Implementation->getFunctionKey(ParentContext: Ctx, Name);
2429 if (!Key)
2430 return std::nullopt;
2431
2432 auto Known = Implementation->GlobalFunctionTable->find(EKey: *Key);
2433 if (Known == Implementation->GlobalFunctionTable->end())
2434 return std::nullopt;
2435
2436 return {Implementation->SwiftVersion, *Known};
2437}
2438
2439template <typename ParameterT>
2440auto APINotesReader::lookupGlobalFunctionImpl(
2441 llvm::StringRef Name, llvm::ArrayRef<ParameterT> Parameters,
2442 std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> {
2443 if (!Implementation->GlobalFunctionTable)
2444 return std::nullopt;
2445
2446 std::optional<FunctionTableKey> Key =
2447 Implementation->getFunctionKey(Ctx, Name, Parameters);
2448 if (!Key)
2449 return std::nullopt;
2450
2451 auto Known = Implementation->GlobalFunctionTable->find(EKey: *Key);
2452 if (Known == Implementation->GlobalFunctionTable->end())
2453 return std::nullopt;
2454
2455 return {Implementation->SwiftVersion, *Known};
2456}
2457
2458auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
2459 -> VersionedInfo<EnumConstantInfo> {
2460 if (!Implementation->EnumConstantTable)
2461 return std::nullopt;
2462
2463 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Str: Name);
2464 if (!NameID)
2465 return std::nullopt;
2466
2467 auto Known = Implementation->EnumConstantTable->find(EKey: *NameID);
2468 if (Known == Implementation->EnumConstantTable->end())
2469 return std::nullopt;
2470
2471 return {Implementation->SwiftVersion, *Known};
2472}
2473
2474auto APINotesReader::lookupTagID(llvm::StringRef Name,
2475 std::optional<Context> ParentCtx)
2476 -> std::optional<ContextID> {
2477 if (!Implementation->ContextIDTable)
2478 return std::nullopt;
2479
2480 std::optional<IdentifierID> TagID = Implementation->getIdentifier(Str: Name);
2481 if (!TagID)
2482 return std::nullopt;
2483
2484 auto KnownID = Implementation->ContextIDTable->find(
2485 EKey: ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2486 if (KnownID == Implementation->ContextIDTable->end())
2487 return std::nullopt;
2488
2489 return ContextID(*KnownID);
2490}
2491
2492auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
2493 -> VersionedInfo<TagInfo> {
2494 if (!Implementation->TagTable)
2495 return std::nullopt;
2496
2497 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Str: Name);
2498 if (!NameID)
2499 return std::nullopt;
2500
2501 SingleDeclTableKey Key(Ctx, *NameID);
2502
2503 auto Known = Implementation->TagTable->find(EKey: Key);
2504 if (Known == Implementation->TagTable->end())
2505 return std::nullopt;
2506
2507 return {Implementation->SwiftVersion, *Known};
2508}
2509
2510auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2511 std::optional<Context> Ctx)
2512 -> VersionedInfo<TypedefInfo> {
2513 if (!Implementation->TypedefTable)
2514 return std::nullopt;
2515
2516 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Str: Name);
2517 if (!NameID)
2518 return std::nullopt;
2519
2520 SingleDeclTableKey Key(Ctx, *NameID);
2521
2522 auto Known = Implementation->TypedefTable->find(EKey: Key);
2523 if (Known == Implementation->TypedefTable->end())
2524 return std::nullopt;
2525
2526 return {Implementation->SwiftVersion, *Known};
2527}
2528
2529auto APINotesReader::lookupNamespaceID(
2530 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2531 -> std::optional<ContextID> {
2532 if (!Implementation->ContextIDTable)
2533 return std::nullopt;
2534
2535 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Str: Name);
2536 if (!NamespaceID)
2537 return std::nullopt;
2538
2539 uint32_t RawParentNamespaceID =
2540 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2541 auto KnownID = Implementation->ContextIDTable->find(
2542 EKey: {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2543 if (KnownID == Implementation->ContextIDTable->end())
2544 return std::nullopt;
2545
2546 return ContextID(*KnownID);
2547}
2548
2549} // namespace api_notes
2550} // namespace clang
2551