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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/APINotes/APINotesReader.cpp