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