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