clang 24.0.0git
APINotesWriter.cpp
Go to the documentation of this file.
1//===-- APINotesWriter.cpp - API Notes Writer -------------------*- 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
10#include "APINotesFormat.h"
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/StringMap.h"
15#include "llvm/Bitstream/BitstreamWriter.h"
16#include "llvm/Support/DJB.h"
17#include "llvm/Support/OnDiskHashTable.h"
18#include "llvm/Support/VersionTuple.h"
19
20namespace clang {
21namespace api_notes {
23 friend class APINotesWriter;
24
25 template <typename T>
26 using VersionedSmallVector =
28
29 std::string ModuleName;
30 const FileEntry *SourceFile;
31
32 /// Scratch space for bitstream writing.
34
35 /// Mapping from strings to identifier IDs.
36 llvm::StringMap<IdentifierID> IdentifierIDs;
37
38 /// Information about contexts (Objective-C classes or protocols or C++
39 /// namespaces).
40 ///
41 /// Indexed by the parent context ID, context kind and the identifier ID of
42 /// this context and provides both the context ID and information describing
43 /// the context within that module.
44 llvm::DenseMap<ContextTableKey,
45 std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
46 Contexts;
47
48 /// Information about parent contexts for each context.
49 ///
50 /// Indexed by context ID, provides the parent context ID.
51 llvm::DenseMap<uint32_t, uint32_t> ParentContexts;
52
53 /// Mapping from context IDs to the kind of context.
54 llvm::DenseMap<unsigned, uint8_t> ContextKinds;
55
56 /// Mapping from context IDs to the identifier ID holding the name.
57 llvm::DenseMap<unsigned, unsigned> ContextNames;
58
59 /// Information about Objective-C properties.
60 ///
61 /// Indexed by the context ID, property name, and whether this is an
62 /// instance property.
63 llvm::DenseMap<
64 std::tuple<unsigned, unsigned, char>,
66 ObjCProperties;
67
68 /// Information about C record fields.
69 ///
70 /// Indexed by the context ID and name ID.
71 llvm::DenseMap<SingleDeclTableKey,
73 Fields;
74
75 /// Information about Objective-C methods.
76 ///
77 /// Indexed by the context ID, selector ID, and Boolean (stored as a char)
78 /// indicating whether this is a class or instance method.
79 llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
81 ObjCMethods;
82
83 /// Information about C++ methods.
84 ///
85 /// Indexed by the context ID, name ID, and optional parameter selector.
86 llvm::DenseMap<FunctionTableKey,
88 CXXMethods;
89
90 /// Mapping from selectors to selector ID.
91 llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
92
93 /// Information about global variables.
94 ///
95 /// Indexed by the context ID, identifier ID.
96 llvm::DenseMap<
99 GlobalVariables;
100
101 /// Information about global functions.
102 ///
103 /// Indexed by the context ID, identifier ID, and optional parameter selector.
104 llvm::DenseMap<
107 GlobalFunctions;
108
109 /// Information about enumerators.
110 ///
111 /// Indexed by the identifier ID.
112 llvm::DenseMap<
114 EnumConstants;
115
116 /// Information about tags.
117 ///
118 /// Indexed by the context ID, identifier ID.
119 llvm::DenseMap<SingleDeclTableKey,
121 Tags;
122
123 /// Information about typedefs.
124 ///
125 /// Indexed by the context ID, identifier ID.
126 llvm::DenseMap<SingleDeclTableKey,
128 Typedefs;
129
130 /// Retrieve the ID for the given identifier.
131 IdentifierID getIdentifier(StringRef Identifier) {
132 if (Identifier.empty())
133 return 0;
134
135 // Add to the identifier table if missing.
136 return IdentifierIDs.try_emplace(Identifier, IdentifierIDs.size() + 1)
137 .first->second;
138 }
139
140 FunctionTableKey getFunctionKey(uint32_t ParentContextID, StringRef Name) {
141 std::optional<FunctionTableKey> Key =
142 getFunctionKeyImpl(ParentContextID, Name,
143 [this](StringRef S) -> std::optional<IdentifierID> {
144 return getIdentifier(S);
145 });
146 assert(Key && "Writer identifier lookup should not fail");
147 return *Key;
148 }
149
150 FunctionTableKey getFunctionKey(uint32_t ParentContextID, StringRef Name,
151 ArrayRef<StringRef> Parameters) {
152 std::optional<FunctionTableKey> Key =
153 getFunctionKeyImpl(ParentContextID, Name, Parameters,
154 [this](StringRef S) -> std::optional<IdentifierID> {
155 return getIdentifier(S);
156 });
157 assert(Key && "Writer identifier lookup should not fail");
158 return *Key;
159 }
160
161 FunctionTableKey getFunctionKey(std::optional<Context> ParentContext,
162 StringRef Name) {
163 uint32_t ParentContextID =
164 ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
165 return getFunctionKey(ParentContextID, Name);
166 }
167
168 FunctionTableKey getFunctionKey(std::optional<Context> ParentContext,
169 StringRef Name,
170 ArrayRef<StringRef> Parameters) {
171 uint32_t ParentContextID =
172 ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1);
173 return getFunctionKey(ParentContextID, Name, Parameters);
174 }
175
176 /// Retrieve the ID for the given selector.
177 SelectorID getSelector(ObjCSelectorRef SelectorRef) {
178 // Translate the selector reference into a stored selector.
179 StoredObjCSelector Selector;
180 Selector.NumArgs = SelectorRef.NumArgs;
181 Selector.Identifiers.reserve(SelectorRef.Identifiers.size());
182 for (auto piece : SelectorRef.Identifiers)
183 Selector.Identifiers.push_back(getIdentifier(piece));
184
185 // Look for the stored selector. Add to the selector table if missing.
186 return SelectorIDs.try_emplace(Selector, SelectorIDs.size()).first->second;
187 }
188
189private:
190 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
191 void writeControlBlock(llvm::BitstreamWriter &Stream);
192 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
193 void writeContextBlock(llvm::BitstreamWriter &Stream);
194 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
195 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
196 void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
197 void writeFieldBlock(llvm::BitstreamWriter &Stream);
198 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
199 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
200 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
201 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
202 void writeTagBlock(llvm::BitstreamWriter &Stream);
203 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
204
205public:
206 Implementation(llvm::StringRef ModuleName, const FileEntry *SF)
207 : ModuleName(std::string(ModuleName)), SourceFile(SF) {}
208
209 void writeToStream(llvm::raw_ostream &OS);
210};
211
214
215 {
216 llvm::BitstreamWriter Stream(Buffer);
217
218 // Emit the signature.
219 for (unsigned char Byte : API_NOTES_SIGNATURE)
220 Stream.Emit(Byte, 8);
221
222 // Emit the blocks.
223 writeBlockInfoBlock(Stream);
224 writeControlBlock(Stream);
225 writeIdentifierBlock(Stream);
226 writeContextBlock(Stream);
227 writeObjCPropertyBlock(Stream);
228 writeObjCMethodBlock(Stream);
229 writeCXXMethodBlock(Stream);
230 writeFieldBlock(Stream);
231 writeObjCSelectorBlock(Stream);
232 writeGlobalVariableBlock(Stream);
233 writeGlobalFunctionBlock(Stream);
234 writeEnumConstantBlock(Stream);
235 writeTagBlock(Stream);
236 writeTypedefBlock(Stream);
237 }
238
239 OS.write(Buffer.data(), Buffer.size());
240 OS.flush();
241}
242
243namespace {
244/// Record the name of a block.
245void emitBlockID(llvm::BitstreamWriter &Stream, unsigned ID,
246 llvm::StringRef Name) {
247 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
249
250 // Emit the block name if present.
251 if (Name.empty())
252 return;
253 Stream.EmitRecord(
254 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
256 const_cast<unsigned char *>(
257 reinterpret_cast<const unsigned char *>(Name.data())),
258 Name.size()));
259}
260
261/// Record the name of a record within a block.
262void emitRecordID(llvm::BitstreamWriter &Stream, unsigned ID,
263 llvm::StringRef Name) {
264 assert(ID < 256 && "can't fit record ID in next to name");
265
267 Buffer.resize(Name.size() + 1);
268 Buffer[0] = ID;
269 memcpy(Buffer.data() + 1, Name.data(), Name.size());
270
271 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
272}
273} // namespace
274
275void APINotesWriter::Implementation::writeBlockInfoBlock(
276 llvm::BitstreamWriter &Stream) {
277 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
278
279#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
280#define BLOCK_RECORD(NameSpace, Block) \
281 emitRecordID(Stream, NameSpace::Block, #Block)
282 BLOCK(CONTROL_BLOCK);
283 BLOCK_RECORD(control_block, METADATA);
284 BLOCK_RECORD(control_block, MODULE_NAME);
285
286 BLOCK(IDENTIFIER_BLOCK);
287 BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);
288
289 BLOCK(OBJC_CONTEXT_BLOCK);
290 BLOCK_RECORD(context_block, CONTEXT_ID_DATA);
291
292 BLOCK(OBJC_PROPERTY_BLOCK);
293 BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);
294
295 BLOCK(OBJC_METHOD_BLOCK);
296 BLOCK_RECORD(objc_method_block, OBJC_METHOD_DATA);
297
298 BLOCK(OBJC_SELECTOR_BLOCK);
299 BLOCK_RECORD(objc_selector_block, OBJC_SELECTOR_DATA);
300
301 BLOCK(GLOBAL_VARIABLE_BLOCK);
302 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
303
304 BLOCK(GLOBAL_FUNCTION_BLOCK);
305 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
306#undef BLOCK_RECORD
307#undef BLOCK
308}
309
310void APINotesWriter::Implementation::writeControlBlock(
311 llvm::BitstreamWriter &Stream) {
312 llvm::BCBlockRAII Scope(Stream, CONTROL_BLOCK_ID, 3);
313
314 control_block::MetadataLayout Metadata(Stream);
315 Metadata.emit(Scratch, VERSION_MAJOR, VERSION_MINOR);
316
317 control_block::ModuleNameLayout ModuleName(Stream);
318 ModuleName.emit(Scratch, this->ModuleName);
319
320 if (SourceFile) {
321 control_block::SourceFileLayout SourceFile(Stream);
322 SourceFile.emit(Scratch, this->SourceFile->getSize(),
323 this->SourceFile->getModificationTime());
324 }
325}
326
327namespace {
328/// Used to serialize the on-disk identifier table.
329class IdentifierTableInfo {
330public:
331 using key_type = StringRef;
332 using key_type_ref = key_type;
333 using data_type = IdentifierID;
334 using data_type_ref = const data_type &;
335 using hash_value_type = uint32_t;
336 using offset_type = unsigned;
337
338 hash_value_type ComputeHash(key_type_ref Key) { return llvm::djbHash(Key); }
339
340 std::pair<unsigned, unsigned>
341 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
342 uint32_t KeyLength = Key.size();
343 uint32_t DataLength = sizeof(uint32_t);
344
345 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
346 writer.write<uint16_t>(KeyLength);
347 writer.write<uint16_t>(DataLength);
348 return {KeyLength, DataLength};
349 }
350
351 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { OS << Key; }
352
353 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
354 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
355 writer.write<uint32_t>(Data);
356 }
357};
358} // namespace
359
360void APINotesWriter::Implementation::writeIdentifierBlock(
361 llvm::BitstreamWriter &Stream) {
362 llvm::BCBlockRAII restoreBlock(Stream, IDENTIFIER_BLOCK_ID, 3);
363
364 if (IdentifierIDs.empty())
365 return;
366
367 llvm::SmallString<4096> HashTableBlob;
368 uint32_t Offset;
369 {
370 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo> Generator;
371 for (auto &II : IdentifierIDs)
372 Generator.insert(II.first(), II.second);
373
374 llvm::raw_svector_ostream BlobStream(HashTableBlob);
375 // Make sure that no bucket is at offset 0
376 llvm::support::endian::write<uint32_t>(BlobStream, 0,
377 llvm::endianness::little);
378 Offset = Generator.Emit(BlobStream);
379 }
380
381 identifier_block::IdentifierDataLayout IdentifierData(Stream);
382 IdentifierData.emit(Scratch, Offset, HashTableBlob);
383}
384
385namespace {
386/// Used to serialize the on-disk Objective-C context table.
387class ContextIDTableInfo {
388public:
389 using key_type = ContextTableKey;
390 using key_type_ref = key_type;
391 using data_type = unsigned;
392 using data_type_ref = const data_type &;
393 using hash_value_type = size_t;
394 using offset_type = unsigned;
395
396 hash_value_type ComputeHash(key_type_ref Key) {
397 return static_cast<size_t>(Key.hashValue());
398 }
399
400 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
401 data_type_ref) {
402 uint32_t KeyLength = sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
403 uint32_t DataLength = sizeof(uint32_t);
404
405 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
406 writer.write<uint16_t>(KeyLength);
407 writer.write<uint16_t>(DataLength);
408 return {KeyLength, DataLength};
409 }
410
411 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
412 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
413 writer.write<uint32_t>(Key.parentContextID);
414 writer.write<uint8_t>(Key.contextKind);
415 writer.write<uint32_t>(Key.contextID);
416 }
417
418 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
419 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
420 writer.write<uint32_t>(Data);
421 }
422};
423
424/// Localized helper to make a type dependent, thwarting template argument
425/// deduction.
426template <typename T> struct MakeDependent { typedef T Type; };
427
428/// Retrieve the serialized size of the given VersionTuple, for use in
429/// on-disk hash tables.
430unsigned getVersionTupleSize(const VersionTuple &VT) {
431 unsigned size = sizeof(uint8_t) + /*major*/ sizeof(uint32_t);
432 if (VT.getMinor())
433 size += sizeof(uint32_t);
434 if (VT.getSubminor())
435 size += sizeof(uint32_t);
436 if (VT.getBuild())
437 size += sizeof(uint32_t);
438 return size;
439}
440
441/// Determine the size of an array of versioned information,
442template <typename T>
443unsigned getVersionedInfoSize(
444 const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI,
445 llvm::function_ref<unsigned(const typename MakeDependent<T>::Type &)>
446 getInfoSize) {
447 unsigned result = sizeof(uint16_t); // # of elements
448 for (const auto &E : VI) {
449 result += getVersionTupleSize(E.first);
450 result += getInfoSize(E.second);
451 }
452 return result;
453}
454
455/// Emit a serialized representation of a version tuple.
456void emitVersionTuple(raw_ostream &OS, const VersionTuple &VT) {
457 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
458
459 // First byte contains the number of components beyond the 'major' component.
460 uint8_t descriptor;
461 if (VT.getBuild())
462 descriptor = 3;
463 else if (VT.getSubminor())
464 descriptor = 2;
465 else if (VT.getMinor())
466 descriptor = 1;
467 else
468 descriptor = 0;
469 writer.write<uint8_t>(descriptor);
470
471 // Write the components.
472 writer.write<uint32_t>(VT.getMajor());
473 if (auto minor = VT.getMinor())
474 writer.write<uint32_t>(*minor);
475 if (auto subminor = VT.getSubminor())
476 writer.write<uint32_t>(*subminor);
477 if (auto build = VT.getBuild())
478 writer.write<uint32_t>(*build);
479}
480
481/// Emit versioned information.
482template <typename T>
483void emitVersionedInfo(
484 raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI,
485 llvm::function_ref<void(raw_ostream &,
486 const typename MakeDependent<T>::Type &)>
487 emitInfo) {
488 std::sort(VI.begin(), VI.end(),
489 [](const std::pair<VersionTuple, T> &LHS,
490 const std::pair<VersionTuple, T> &RHS) -> bool {
491 assert((&LHS == &RHS || LHS.first != RHS.first) &&
492 "two entries for the same version");
493 return LHS.first < RHS.first;
494 });
495
496 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
497 writer.write<uint16_t>(VI.size());
498 for (const auto &E : VI) {
499 emitVersionTuple(OS, E.first);
500 emitInfo(OS, E.second);
501 }
502}
503
504static unsigned getFunctionTableKeyLength(const FunctionTableKey &Key) {
506 (Key.parameterTypeIDs ? Key.parameterTypeIDs->size() * sizeof(uint32_t)
507 : 0);
508}
509
510static void emitFunctionTableKey(raw_ostream &OS, const FunctionTableKey &Key) {
511 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
512 writer.write<uint32_t>(Key.parentContextID);
513 writer.write<uint32_t>(Key.nameID);
514 writer.write<uint8_t>(Key.parameterTypeIDs ? FunctionKeyHasParameterSelector
515 : 0);
516 writer.write<uint16_t>(Key.parameterTypeIDs ? Key.parameterTypeIDs->size()
517 : 0);
518 if (Key.parameterTypeIDs)
519 for (IdentifierID TypeID : *Key.parameterTypeIDs)
520 writer.write<uint32_t>(TypeID);
521}
522
523/// On-disk hash table info key base for handling versioned data.
524template <typename Derived, typename KeyType, typename UnversionedDataType>
525class VersionedTableInfo {
526 Derived &asDerived() { return *static_cast<Derived *>(this); }
527
528 const Derived &asDerived() const {
529 return *static_cast<const Derived *>(this);
530 }
531
532public:
533 using key_type = KeyType;
534 using key_type_ref = key_type;
535 using data_type =
536 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
537 using data_type_ref = data_type &;
538 using hash_value_type = size_t;
539 using offset_type = unsigned;
540
541 std::pair<unsigned, unsigned>
542 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) {
543 uint32_t KeyLength = asDerived().getKeyLength(Key);
544 uint32_t DataLength =
545 getVersionedInfoSize(Data, [this](const UnversionedDataType &UI) {
546 return asDerived().getUnversionedInfoSize(UI);
547 });
548
549 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
550 writer.write<uint16_t>(KeyLength);
551 writer.write<uint16_t>(DataLength);
552 return {KeyLength, DataLength};
553 }
554
555 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
556 emitVersionedInfo(
557 OS, Data, [this](llvm::raw_ostream &OS, const UnversionedDataType &UI) {
558 asDerived().emitUnversionedInfo(OS, UI);
559 });
560 }
561};
562
563/// Emit a serialized representation of the common entity information.
564void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) {
565 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
566
567 uint8_t payload = 0;
568 if (auto safety = CEI.getSwiftSafety()) {
569 payload = static_cast<unsigned>(*safety);
570 payload <<= 1;
571 payload |= 0x01;
572 }
573 payload <<= 2;
574 if (auto swiftPrivate = CEI.isSwiftPrivate()) {
575 payload |= 0x01;
576 if (*swiftPrivate)
577 payload |= 0x02;
578 }
579 payload <<= 1;
580 payload |= CEI.Unavailable;
581 payload <<= 1;
582 payload |= CEI.UnavailableInSwift;
583
584 writer.write<uint8_t>(payload);
585
586 writer.write<uint16_t>(CEI.UnavailableMsg.size());
587 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
588
589 writer.write<uint16_t>(CEI.SwiftName.size());
590 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
591}
592
593/// Retrieve the serialized size of the given CommonEntityInfo, for use in
594/// on-disk hash tables.
595unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
596 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
597}
598
599// Retrieve the serialized size of the given CommonTypeInfo, for use
600// in on-disk hash tables.
601unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
602 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
603 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
604 (CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
605 getCommonEntityInfoSize(CTI);
606}
607
608/// Emit a serialized representation of the common type information.
609void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
610 emitCommonEntityInfo(OS, CTI);
611
612 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
613 if (auto swiftBridge = CTI.getSwiftBridge()) {
614 writer.write<uint16_t>(swiftBridge->size() + 1);
615 OS.write(swiftBridge->c_str(), swiftBridge->size());
616 } else {
617 writer.write<uint16_t>(0);
618 }
619 if (auto nsErrorDomain = CTI.getNSErrorDomain()) {
620 writer.write<uint16_t>(nsErrorDomain->size() + 1);
621 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
622 } else {
623 writer.write<uint16_t>(0);
624 }
625 if (auto conformance = CTI.getSwiftConformance()) {
626 writer.write<uint16_t>(conformance->size() + 1);
627 OS.write(conformance->c_str(), conformance->size());
628 } else {
629 writer.write<uint16_t>(0);
630 }
631}
632
633/// Used to serialize the on-disk Objective-C property table.
634class ContextInfoTableInfo
635 : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
636public:
637 unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }
638
639 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
640 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
641 writer.write<uint32_t>(Key);
642 }
643
644 hash_value_type ComputeHash(key_type_ref Key) {
645 return static_cast<size_t>(llvm::hash_value(Key));
646 }
647
648 unsigned getUnversionedInfoSize(const ContextInfo &OCI) {
649 return getCommonTypeInfoSize(OCI) + 1;
650 }
651
652 void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) {
653 emitCommonTypeInfo(OS, OCI);
654
655 uint8_t payload = 0;
656 if (auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
657 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
658 payload <<= 2;
659 if (auto swiftObjCMembers = OCI.getSwiftObjCMembers())
660 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
661 payload <<= 3;
662 if (auto nullable = OCI.getDefaultNullability())
663 payload |= (0x01 << 2) | static_cast<uint8_t>(*nullable);
664 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
665
666 OS << payload;
667 }
668};
669} // namespace
670
671void APINotesWriter::Implementation::writeContextBlock(
672 llvm::BitstreamWriter &Stream) {
673 llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);
674
675 if (Contexts.empty())
676 return;
677
678 {
679 llvm::SmallString<4096> HashTableBlob;
680 uint32_t Offset;
681 {
682 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator;
683 for (auto &OC : Contexts)
684 Generator.insert(OC.first, OC.second.first);
685
686 llvm::raw_svector_ostream BlobStream(HashTableBlob);
687 // Make sure that no bucket is at offset 0
688 llvm::support::endian::write<uint32_t>(BlobStream, 0,
689 llvm::endianness::little);
690 Offset = Generator.Emit(BlobStream);
691 }
692
693 context_block::ContextIDLayout ContextID(Stream);
694 ContextID.emit(Scratch, Offset, HashTableBlob);
695 }
696
697 {
698 llvm::SmallString<4096> HashTableBlob;
699 uint32_t Offset;
700 {
701 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator;
702 for (auto &OC : Contexts)
703 Generator.insert(OC.second.first, OC.second.second);
704
705 llvm::raw_svector_ostream BlobStream(HashTableBlob);
706 // Make sure that no bucket is at offset 0
707 llvm::support::endian::write<uint32_t>(BlobStream, 0,
708 llvm::endianness::little);
709 Offset = Generator.Emit(BlobStream);
710 }
711
712 context_block::ContextInfoLayout ContextInfo(Stream);
713 ContextInfo.emit(Scratch, Offset, HashTableBlob);
714 }
715}
716
717namespace {
718/// Retrieve the serialized size of the given VariableInfo, for use in
719/// on-disk hash tables.
720unsigned getVariableInfoSize(const VariableInfo &VI) {
721 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
722}
723unsigned getParamInfoSize(const ParamInfo &PI);
724
725/// Emit a serialized representation of the variable information.
726void emitVariableInfo(raw_ostream &OS, const VariableInfo &VI) {
727 emitCommonEntityInfo(OS, VI);
728
729 uint8_t bytes[2] = {0, 0};
730 if (auto nullable = VI.getNullability()) {
731 bytes[0] = 1;
732 bytes[1] = static_cast<uint8_t>(*nullable);
733 } else {
734 // Nothing to do.
735 }
736
737 OS.write(reinterpret_cast<const char *>(bytes), 2);
738
739 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
740 writer.write<uint16_t>(VI.getType().size());
741 OS.write(VI.getType().data(), VI.getType().size());
742}
743
744/// Used to serialize the on-disk Objective-C property table.
745class ObjCPropertyTableInfo
746 : public VersionedTableInfo<ObjCPropertyTableInfo,
747 std::tuple<unsigned, unsigned, char>,
748 ObjCPropertyInfo> {
749public:
750 unsigned getKeyLength(key_type_ref) {
751 return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
752 }
753
754 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
755 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
756 writer.write<uint32_t>(std::get<0>(Key));
757 writer.write<uint32_t>(std::get<1>(Key));
758 writer.write<uint8_t>(std::get<2>(Key));
759 }
760
761 hash_value_type ComputeHash(key_type_ref Key) {
762 return static_cast<size_t>(llvm::hash_value(Key));
763 }
764
765 unsigned getUnversionedInfoSize(const ObjCPropertyInfo &OPI) {
766 return getVariableInfoSize(OPI) + 1;
767 }
768
769 void emitUnversionedInfo(raw_ostream &OS, const ObjCPropertyInfo &OPI) {
770 emitVariableInfo(OS, OPI);
771
772 uint8_t flags = 0;
773 if (auto value = OPI.getSwiftImportAsAccessors()) {
774 flags |= 1 << 0;
775 flags |= value.value() << 1;
776 }
777 OS << flags;
778 }
779};
780} // namespace
781
782void APINotesWriter::Implementation::writeObjCPropertyBlock(
783 llvm::BitstreamWriter &Stream) {
784 llvm::BCBlockRAII Scope(Stream, OBJC_PROPERTY_BLOCK_ID, 3);
785
786 if (ObjCProperties.empty())
787 return;
788
789 {
790 llvm::SmallString<4096> HashTableBlob;
791 uint32_t Offset;
792 {
793 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo> Generator;
794 for (auto &OP : ObjCProperties)
795 Generator.insert(OP.first, OP.second);
796
797 llvm::raw_svector_ostream BlobStream(HashTableBlob);
798 // Make sure that no bucket is at offset 0
799 llvm::support::endian::write<uint32_t>(BlobStream, 0,
800 llvm::endianness::little);
801 Offset = Generator.Emit(BlobStream);
802 }
803
804 objc_property_block::ObjCPropertyDataLayout ObjCPropertyData(Stream);
805 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
806 }
807}
808
809namespace {
810unsigned getFunctionInfoSize(const FunctionInfo &);
811void emitFunctionInfo(llvm::raw_ostream &, const FunctionInfo &);
812void emitParamInfo(raw_ostream &OS, const ParamInfo &PI);
813
814/// Used to serialize the on-disk Objective-C method table.
815class ObjCMethodTableInfo
816 : public VersionedTableInfo<ObjCMethodTableInfo,
817 std::tuple<unsigned, unsigned, char>,
818 ObjCMethodInfo> {
819public:
820 unsigned getKeyLength(key_type_ref) {
821 return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
822 }
823
824 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
825 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
826 writer.write<uint32_t>(std::get<0>(Key));
827 writer.write<uint32_t>(std::get<1>(Key));
828 writer.write<uint8_t>(std::get<2>(Key));
829 }
830
831 hash_value_type ComputeHash(key_type_ref key) {
832 return static_cast<size_t>(llvm::hash_value(key));
833 }
834
835 unsigned getUnversionedInfoSize(const ObjCMethodInfo &OMI) {
836 auto size = getFunctionInfoSize(OMI) + 1;
837 if (OMI.Self)
838 size += getParamInfoSize(*OMI.Self);
839 return size;
840 }
841
842 void emitUnversionedInfo(raw_ostream &OS, const ObjCMethodInfo &OMI) {
843 uint8_t flags = 0;
844 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
845 flags = (flags << 1) | OMI.DesignatedInit;
846 flags = (flags << 1) | OMI.RequiredInit;
847 flags = (flags << 1) | static_cast<bool>(OMI.Self);
848 writer.write<uint8_t>(flags);
849
850 emitFunctionInfo(OS, OMI);
851
852 if (OMI.Self)
853 emitParamInfo(OS, *OMI.Self);
854 }
855};
856
857/// Used to serialize the on-disk C++ method table.
858class CXXMethodTableInfo
859 : public VersionedTableInfo<CXXMethodTableInfo, FunctionTableKey,
860 CXXMethodInfo> {
861public:
862 unsigned getKeyLength(key_type_ref Key) {
863 return getFunctionTableKeyLength(Key);
864 }
865
866 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
867 emitFunctionTableKey(OS, Key);
868 }
869
870 hash_value_type ComputeHash(key_type_ref key) {
871 return static_cast<size_t>(key.hashValue());
872 }
873
874 unsigned getUnversionedInfoSize(const CXXMethodInfo &MI) {
875 auto size = getFunctionInfoSize(MI) + 1;
876 if (MI.This)
877 size += getParamInfoSize(*MI.This);
878 return size;
879 }
880
881 void emitUnversionedInfo(raw_ostream &OS, const CXXMethodInfo &MI) {
882 uint8_t flags = 0;
883 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
884 flags = (flags << 1) | static_cast<bool>(MI.This);
885 writer.write<uint8_t>(flags);
886
887 emitFunctionInfo(OS, MI);
888 if (MI.This)
889 emitParamInfo(OS, *MI.This);
890 }
891};
892} // namespace
893
894void APINotesWriter::Implementation::writeObjCMethodBlock(
895 llvm::BitstreamWriter &Stream) {
896 llvm::BCBlockRAII Scope(Stream, OBJC_METHOD_BLOCK_ID, 3);
897
898 if (ObjCMethods.empty())
899 return;
900
901 {
902 llvm::SmallString<4096> HashTableBlob;
903 uint32_t Offset;
904 {
905 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo> Generator;
906 for (auto &OM : ObjCMethods)
907 Generator.insert(OM.first, OM.second);
908
909 llvm::raw_svector_ostream BlobStream(HashTableBlob);
910 // Make sure that no bucket is at offset 0
911 llvm::support::endian::write<uint32_t>(BlobStream, 0,
912 llvm::endianness::little);
913 Offset = Generator.Emit(BlobStream);
914 }
915
916 objc_method_block::ObjCMethodDataLayout ObjCMethodData(Stream);
917 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
918 }
919}
920
921void APINotesWriter::Implementation::writeCXXMethodBlock(
922 llvm::BitstreamWriter &Stream) {
923 llvm::BCBlockRAII Scope(Stream, CXX_METHOD_BLOCK_ID, 3);
924
925 if (CXXMethods.empty())
926 return;
927
928 {
929 llvm::SmallString<4096> HashTableBlob;
930 uint32_t Offset;
931 {
932 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo> Generator;
933 for (auto &MD : CXXMethods)
934 Generator.insert(MD.first, MD.second);
935
936 llvm::raw_svector_ostream BlobStream(HashTableBlob);
937 // Make sure that no bucket is at offset 0
938 llvm::support::endian::write<uint32_t>(BlobStream, 0,
939 llvm::endianness::little);
940 Offset = Generator.Emit(BlobStream);
941 }
942
943 cxx_method_block::CXXMethodDataLayout CXXMethodData(Stream);
944 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
945 }
946}
947
948namespace {
949/// Used to serialize the on-disk C field table.
950class FieldTableInfo
951 : public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
952public:
953 unsigned getKeyLength(key_type_ref) {
954 return sizeof(uint32_t) + sizeof(uint32_t);
955 }
956
957 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
958 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
959 writer.write<uint32_t>(Key.parentContextID);
960 writer.write<uint32_t>(Key.nameID);
961 }
962
963 hash_value_type ComputeHash(key_type_ref key) {
964 return static_cast<size_t>(key.hashValue());
965 }
966
967 unsigned getUnversionedInfoSize(const FieldInfo &FI) {
968 return getVariableInfoSize(FI);
969 }
970
971 void emitUnversionedInfo(raw_ostream &OS, const FieldInfo &FI) {
972 emitVariableInfo(OS, FI);
973 }
974};
975} // namespace
976
977void APINotesWriter::Implementation::writeFieldBlock(
978 llvm::BitstreamWriter &Stream) {
979 llvm::BCBlockRAII Scope(Stream, FIELD_BLOCK_ID, 3);
980
981 if (Fields.empty())
982 return;
983
984 {
985 llvm::SmallString<4096> HashTableBlob;
986 uint32_t Offset;
987 {
988 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo> Generator;
989 for (auto &FD : Fields)
990 Generator.insert(FD.first, FD.second);
991
992 llvm::raw_svector_ostream BlobStream(HashTableBlob);
993 // Make sure that no bucket is at offset 0
994 llvm::support::endian::write<uint32_t>(BlobStream, 0,
995 llvm::endianness::little);
996 Offset = Generator.Emit(BlobStream);
997 }
998
999 field_block::FieldDataLayout FieldData(Stream);
1000 FieldData.emit(Scratch, Offset, HashTableBlob);
1001 }
1002}
1003
1004namespace {
1005/// Used to serialize the on-disk Objective-C selector table.
1006class ObjCSelectorTableInfo {
1007public:
1008 using key_type = StoredObjCSelector;
1009 using key_type_ref = const key_type &;
1010 using data_type = SelectorID;
1011 using data_type_ref = data_type;
1012 using hash_value_type = unsigned;
1013 using offset_type = unsigned;
1014
1015 hash_value_type ComputeHash(key_type_ref Key) {
1016 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
1017 }
1018
1019 std::pair<unsigned, unsigned>
1020 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
1021 uint32_t KeyLength =
1022 sizeof(uint16_t) + sizeof(uint32_t) * Key.Identifiers.size();
1023 uint32_t DataLength = sizeof(uint32_t);
1024
1025 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1026 writer.write<uint16_t>(KeyLength);
1027 writer.write<uint16_t>(DataLength);
1028 return {KeyLength, DataLength};
1029 }
1030
1031 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1032 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1033 writer.write<uint16_t>(Key.NumArgs);
1034 for (auto Identifier : Key.Identifiers)
1035 writer.write<uint32_t>(Identifier);
1036 }
1037
1038 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
1039 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1040 writer.write<uint32_t>(Data);
1041 }
1042};
1043} // namespace
1044
1045void APINotesWriter::Implementation::writeObjCSelectorBlock(
1046 llvm::BitstreamWriter &Stream) {
1047 llvm::BCBlockRAII Scope(Stream, OBJC_SELECTOR_BLOCK_ID, 3);
1048
1049 if (SelectorIDs.empty())
1050 return;
1051
1052 {
1053 llvm::SmallString<4096> HashTableBlob;
1054 uint32_t Offset;
1055 {
1056 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo> Generator;
1057 for (auto &S : SelectorIDs)
1058 Generator.insert(S.first, S.second);
1059
1060 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1061 // Make sure that no bucket is at offset 0
1062 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1063 llvm::endianness::little);
1064 Offset = Generator.Emit(BlobStream);
1065 }
1066
1067 objc_selector_block::ObjCSelectorDataLayout ObjCSelectorData(Stream);
1068 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
1069 }
1070}
1071
1072namespace {
1073/// Used to serialize the on-disk global variable table.
1074class GlobalVariableTableInfo
1075 : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
1076 GlobalVariableInfo> {
1077public:
1078 unsigned getKeyLength(key_type_ref) {
1079 return sizeof(uint32_t) + sizeof(uint32_t);
1080 }
1081
1082 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1083 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1084 writer.write<uint32_t>(Key.parentContextID);
1085 writer.write<uint32_t>(Key.nameID);
1086 }
1087
1088 hash_value_type ComputeHash(key_type_ref Key) {
1089 return static_cast<size_t>(Key.hashValue());
1090 }
1091
1092 unsigned getUnversionedInfoSize(const GlobalVariableInfo &GVI) {
1093 return getVariableInfoSize(GVI);
1094 }
1095
1096 void emitUnversionedInfo(raw_ostream &OS, const GlobalVariableInfo &GVI) {
1097 emitVariableInfo(OS, GVI);
1098 }
1099};
1100} // namespace
1101
1102void APINotesWriter::Implementation::writeGlobalVariableBlock(
1103 llvm::BitstreamWriter &Stream) {
1104 llvm::BCBlockRAII Scope(Stream, GLOBAL_VARIABLE_BLOCK_ID, 3);
1105
1106 if (GlobalVariables.empty())
1107 return;
1108
1109 {
1110 llvm::SmallString<4096> HashTableBlob;
1111 uint32_t Offset;
1112 {
1113 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo> Generator;
1114 for (auto &GV : GlobalVariables)
1115 Generator.insert(GV.first, GV.second);
1116
1117 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1118 // Make sure that no bucket is at offset 0
1119 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1120 llvm::endianness::little);
1121 Offset = Generator.Emit(BlobStream);
1122 }
1123
1124 global_variable_block::GlobalVariableDataLayout GlobalVariableData(Stream);
1125 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1126 }
1127}
1128
1129namespace {
1130void emitBoundsSafetyInfo(raw_ostream &OS, const BoundsSafetyInfo &BSI) {
1131 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1132 uint8_t flags = 0;
1133 if (auto kind = BSI.getKind()) {
1135 flags |= 0x01; // 1 bit
1136 flags |= (uint8_t)*kind << 1; // 3 bits
1137 }
1138 flags <<= 4;
1139 if (auto level = BSI.getLevel()) {
1140 assert(*level < (1u << 3));
1141 flags |= 0x01; // 1 bit
1142 flags |= (uint8_t)*level << 1; // 3 bits
1143 }
1144
1145 writer.write<uint8_t>(flags);
1146 writer.write<uint16_t>(BSI.ExternalBounds.size());
1147 writer.write(
1148 ArrayRef<char>{BSI.ExternalBounds.data(), BSI.ExternalBounds.size()});
1149}
1150
1151unsigned getBoundsSafetyInfoSize(const BoundsSafetyInfo &BSI) {
1152 return 1 + sizeof(uint16_t) + BSI.ExternalBounds.size();
1153}
1154
1155unsigned getParamInfoSize(const ParamInfo &PI) {
1156 unsigned BSISize = 0;
1157 if (auto BSI = PI.BoundsSafety)
1158 BSISize = getBoundsSafetyInfoSize(*BSI);
1159 return getVariableInfoSize(PI) + 1 + BSISize;
1160}
1161
1162void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) {
1163 emitVariableInfo(OS, PI);
1164
1165 uint8_t flags = 0;
1166 if (PI.BoundsSafety)
1167 flags |= 0x01;
1168 flags <<= 2;
1169 if (auto noescape = PI.isNoEscape()) {
1170 flags |= 0x01;
1171 if (*noescape)
1172 flags |= 0x02;
1173 }
1174 flags <<= 2;
1175 if (auto lifetimebound = PI.isLifetimebound()) {
1176 flags |= 0x01;
1177 if (*lifetimebound)
1178 flags |= 0x02;
1179 }
1180 flags <<= 3;
1181 if (auto RCC = PI.getRetainCountConvention())
1182 flags |= static_cast<uint8_t>(RCC.value()) + 1;
1183
1184 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1185 writer.write<uint8_t>(flags);
1186 if (auto BSI = PI.BoundsSafety)
1187 emitBoundsSafetyInfo(OS, *BSI);
1188}
1189
1190/// Retrieve the serialized size of the given FunctionInfo, for use in on-disk
1191/// hash tables.
1192unsigned getFunctionInfoSize(const FunctionInfo &FI) {
1193 unsigned size = getCommonEntityInfoSize(FI) + 2 + sizeof(uint64_t);
1194 size += sizeof(uint16_t);
1195 for (const auto &P : FI.Params)
1196 size += getParamInfoSize(P);
1197 size += sizeof(uint16_t) + FI.ResultType.size();
1198 size += sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
1199 return size;
1200}
1201
1202/// Emit a serialized representation of the function information.
1203void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) {
1204 emitCommonEntityInfo(OS, FI);
1205
1206 uint8_t flags = 0;
1207 flags |= FI.NullabilityAudited;
1208 flags <<= 3;
1209 if (auto RCC = FI.getRetainCountConvention())
1210 flags |= static_cast<uint8_t>(RCC.value()) + 1;
1211 flags <<= 0x01;
1212 flags |= FI.UnsafeBufferUsage;
1213
1214 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1215
1216 writer.write<uint8_t>(flags);
1217 writer.write<uint8_t>(FI.NumAdjustedNullable);
1218 writer.write<uint64_t>(FI.NullabilityPayload);
1219
1220 writer.write<uint16_t>(FI.Params.size());
1221 for (const auto &PI : FI.Params)
1222 emitParamInfo(OS, PI);
1223
1224 writer.write<uint16_t>(FI.ResultType.size());
1225 writer.write(ArrayRef<char>{FI.ResultType});
1226 writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1227 writer.write(ArrayRef<char>{FI.SwiftReturnOwnership});
1228}
1229
1230/// Used to serialize the on-disk global function table.
1231class GlobalFunctionTableInfo
1232 : public VersionedTableInfo<GlobalFunctionTableInfo, FunctionTableKey,
1233 GlobalFunctionInfo> {
1234public:
1235 unsigned getKeyLength(key_type_ref Key) {
1236 return getFunctionTableKeyLength(Key);
1237 }
1238
1239 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1240 emitFunctionTableKey(OS, Key);
1241 }
1242
1243 hash_value_type ComputeHash(key_type_ref Key) {
1244 return static_cast<size_t>(Key.hashValue());
1245 }
1246
1247 unsigned getUnversionedInfoSize(const GlobalFunctionInfo &GFI) {
1248 return getFunctionInfoSize(GFI);
1249 }
1250
1251 void emitUnversionedInfo(raw_ostream &OS, const GlobalFunctionInfo &GFI) {
1252 emitFunctionInfo(OS, GFI);
1253 }
1254};
1255} // namespace
1256
1257void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1258 llvm::BitstreamWriter &Stream) {
1259 llvm::BCBlockRAII Scope(Stream, GLOBAL_FUNCTION_BLOCK_ID, 3);
1260
1261 if (GlobalFunctions.empty())
1262 return;
1263
1264 {
1265 llvm::SmallString<4096> HashTableBlob;
1266 uint32_t Offset;
1267 {
1268 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo> Generator;
1269 for (auto &F : GlobalFunctions)
1270 Generator.insert(F.first, F.second);
1271
1272 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1273 // Make sure that no bucket is at offset 0
1274 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1275 llvm::endianness::little);
1276 Offset = Generator.Emit(BlobStream);
1277 }
1278
1279 global_function_block::GlobalFunctionDataLayout GlobalFunctionData(Stream);
1280 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1281 }
1282}
1283
1284namespace {
1285/// Used to serialize the on-disk global enum constant.
1286class EnumConstantTableInfo
1287 : public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1288 EnumConstantInfo> {
1289public:
1290 unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }
1291
1292 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1293 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1294 writer.write<uint32_t>(Key);
1295 }
1296
1297 hash_value_type ComputeHash(key_type_ref Key) {
1298 return static_cast<size_t>(llvm::hash_value(Key));
1299 }
1300
1301 unsigned getUnversionedInfoSize(const EnumConstantInfo &ECI) {
1302 return getCommonEntityInfoSize(ECI);
1303 }
1304
1305 void emitUnversionedInfo(raw_ostream &OS, const EnumConstantInfo &ECI) {
1306 emitCommonEntityInfo(OS, ECI);
1307 }
1308};
1309} // namespace
1310
1311void APINotesWriter::Implementation::writeEnumConstantBlock(
1312 llvm::BitstreamWriter &Stream) {
1313 llvm::BCBlockRAII Scope(Stream, ENUM_CONSTANT_BLOCK_ID, 3);
1314
1315 if (EnumConstants.empty())
1316 return;
1317
1318 {
1319 llvm::SmallString<4096> HashTableBlob;
1320 uint32_t Offset;
1321 {
1322 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo> Generator;
1323 for (auto &EC : EnumConstants)
1324 Generator.insert(EC.first, EC.second);
1325
1326 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1327 // Make sure that no bucket is at offset 0
1328 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1329 llvm::endianness::little);
1330 Offset = Generator.Emit(BlobStream);
1331 }
1332
1333 enum_constant_block::EnumConstantDataLayout EnumConstantData(Stream);
1334 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1335 }
1336}
1337
1338namespace {
1339template <typename Derived, typename UnversionedDataType>
1340class CommonTypeTableInfo
1341 : public VersionedTableInfo<Derived, SingleDeclTableKey,
1342 UnversionedDataType> {
1343public:
1344 using key_type_ref = typename CommonTypeTableInfo::key_type_ref;
1345 using hash_value_type = typename CommonTypeTableInfo::hash_value_type;
1346
1347 unsigned getKeyLength(key_type_ref) {
1348 return sizeof(uint32_t) + sizeof(IdentifierID);
1349 }
1350
1351 void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1352 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1353 writer.write<uint32_t>(Key.parentContextID);
1354 writer.write<IdentifierID>(Key.nameID);
1355 }
1356
1357 hash_value_type ComputeHash(key_type_ref Key) {
1358 return static_cast<size_t>(Key.hashValue());
1359 }
1360
1361 unsigned getUnversionedInfoSize(const UnversionedDataType &UDT) {
1362 return getCommonTypeInfoSize(UDT);
1363 }
1364
1365 void emitUnversionedInfo(raw_ostream &OS, const UnversionedDataType &UDT) {
1366 emitCommonTypeInfo(OS, UDT);
1367 }
1368};
1369
1370/// Used to serialize the on-disk tag table.
1371class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1372public:
1373 unsigned getUnversionedInfoSize(const TagInfo &TI) {
1374 // clang-format off
1375 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1376 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1377 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1378 2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
1379 2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1380 3 + getCommonTypeInfoSize(TI);
1381 // clang-format on
1382 }
1383
1384 void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
1385 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1386
1387 uint8_t Flags = 0;
1388 if (auto extensibility = TI.EnumExtensibility) {
1389 Flags |= static_cast<uint8_t>(extensibility.value()) + 1;
1390 assert((Flags < (1 << 2)) && "must fit in two bits");
1391 }
1392
1393 Flags <<= 2;
1394 if (auto value = TI.isFlagEnum())
1395 Flags |= (value.value() << 1 | 1 << 0);
1396
1397 writer.write<uint8_t>(Flags);
1398
1399 if (auto Copyable = TI.isSwiftCopyable())
1400 writer.write<uint8_t>(*Copyable ? kSwiftConforms : kSwiftDoesNotConform);
1401 else
1402 writer.write<uint8_t>(0);
1403
1404 if (auto Escapable = TI.isSwiftEscapable())
1405 writer.write<uint8_t>(*Escapable ? kSwiftConforms : kSwiftDoesNotConform);
1406 else
1407 writer.write<uint8_t>(0);
1408
1409 if (auto ImportAs = TI.SwiftImportAs) {
1410 writer.write<uint16_t>(ImportAs->size() + 1);
1411 OS.write(ImportAs->c_str(), ImportAs->size());
1412 } else {
1413 writer.write<uint16_t>(0);
1414 }
1415 if (auto RetainOp = TI.SwiftRetainOp) {
1416 writer.write<uint16_t>(RetainOp->size() + 1);
1417 OS.write(RetainOp->c_str(), RetainOp->size());
1418 } else {
1419 writer.write<uint16_t>(0);
1420 }
1421 if (auto ReleaseOp = TI.SwiftReleaseOp) {
1422 writer.write<uint16_t>(ReleaseOp->size() + 1);
1423 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1424 } else {
1425 writer.write<uint16_t>(0);
1426 }
1427 if (auto DefaultOwnership = TI.SwiftDefaultOwnership) {
1428 writer.write<uint16_t>(DefaultOwnership->size() + 1);
1429 OS.write(DefaultOwnership->c_str(), DefaultOwnership->size());
1430 } else {
1431 writer.write<uint16_t>(0);
1432 }
1433 if (auto DestroyOp = TI.SwiftDestroyOp) {
1434 writer.write<uint16_t>(DestroyOp->size() + 1);
1435 OS.write(DestroyOp->c_str(), DestroyOp->size());
1436 } else {
1437 writer.write<uint16_t>(0);
1438 }
1439
1440 emitCommonTypeInfo(OS, TI);
1441 }
1442};
1443} // namespace
1444
1445void APINotesWriter::Implementation::writeTagBlock(
1446 llvm::BitstreamWriter &Stream) {
1447 llvm::BCBlockRAII Scope(Stream, TAG_BLOCK_ID, 3);
1448
1449 if (Tags.empty())
1450 return;
1451
1452 {
1453 llvm::SmallString<4096> HashTableBlob;
1454 uint32_t Offset;
1455 {
1456 llvm::OnDiskChainedHashTableGenerator<TagTableInfo> Generator;
1457 for (auto &T : Tags)
1458 Generator.insert(T.first, T.second);
1459
1460 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1461 // Make sure that no bucket is at offset 0
1462 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1463 llvm::endianness::little);
1464 Offset = Generator.Emit(BlobStream);
1465 }
1466
1467 tag_block::TagDataLayout TagData(Stream);
1468 TagData.emit(Scratch, Offset, HashTableBlob);
1469 }
1470}
1471
1472namespace {
1473/// Used to serialize the on-disk typedef table.
1474class TypedefTableInfo
1475 : public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1476public:
1477 unsigned getUnversionedInfoSize(const TypedefInfo &TI) {
1478 return 1 + getCommonTypeInfoSize(TI);
1479 }
1480
1481 void emitUnversionedInfo(raw_ostream &OS, const TypedefInfo &TI) {
1482 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1483
1484 uint8_t Flags = 0;
1485 if (auto swiftWrapper = TI.SwiftWrapper)
1486 Flags |= static_cast<uint8_t>(*swiftWrapper) + 1;
1487
1488 writer.write<uint8_t>(Flags);
1489
1490 emitCommonTypeInfo(OS, TI);
1491 }
1492};
1493} // namespace
1494
1495void APINotesWriter::Implementation::writeTypedefBlock(
1496 llvm::BitstreamWriter &Stream) {
1497 llvm::BCBlockRAII Scope(Stream, TYPEDEF_BLOCK_ID, 3);
1498
1499 if (Typedefs.empty())
1500 return;
1501
1502 {
1503 llvm::SmallString<4096> HashTableBlob;
1504 uint32_t Offset;
1505 {
1506 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo> Generator;
1507 for (auto &T : Typedefs)
1508 Generator.insert(T.first, T.second);
1509
1510 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1511 // Make sure that no bucket is at offset 0
1512 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1513 llvm::endianness::little);
1514 Offset = Generator.Emit(BlobStream);
1515 }
1516
1517 typedef_block::TypedefDataLayout TypedefData(Stream);
1518 TypedefData.emit(Scratch, Offset, HashTableBlob);
1519 }
1520}
1521
1522// APINotesWriter
1523
1524APINotesWriter::APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF)
1525 : Implementation(new class Implementation(ModuleName, SF)) {}
1526
1528
1529void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
1531}
1532
1533ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID,
1534 llvm::StringRef Name, ContextKind Kind,
1535 const ContextInfo &Info,
1536 llvm::VersionTuple SwiftVersion) {
1537 IdentifierID NameID = Implementation->getIdentifier(Name);
1538
1539 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1540 ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
1541 auto Known = Implementation->Contexts.find(Key);
1542 if (Known == Implementation->Contexts.end()) {
1543 unsigned NextID = Implementation->Contexts.size() + 1;
1544
1545 Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
1546 Known = Implementation->Contexts
1547 .insert(std::make_pair(
1548 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1549 .first;
1550
1551 Implementation->ContextNames[NextID] = NameID;
1552 Implementation->ParentContexts[NextID] = RawParentCtxID;
1553 Implementation->ContextKinds[NextID] = static_cast<uint8_t>(Kind);
1554 }
1555
1556 // Add this version information.
1557 auto &VersionedVec = Known->second.second;
1558 bool Found = false;
1559 for (auto &Versioned : VersionedVec) {
1560 if (Versioned.first == SwiftVersion) {
1561 Versioned.second |= Info;
1562 Found = true;
1563 break;
1564 }
1565 }
1566
1567 if (!Found)
1568 VersionedVec.push_back({SwiftVersion, Info});
1569
1570 return ContextID(Known->second.first);
1571}
1572
1574 bool IsInstanceProperty,
1575 const ObjCPropertyInfo &Info,
1576 VersionTuple SwiftVersion) {
1577 IdentifierID NameID = Implementation->getIdentifier(Name);
1579 ->ObjCProperties[std::make_tuple(CtxID.Value, NameID, IsInstanceProperty)]
1580 .push_back({SwiftVersion, Info});
1581}
1582
1584 bool IsInstanceMethod,
1585 const ObjCMethodInfo &Info,
1586 VersionTuple SwiftVersion) {
1587 SelectorID SelID = Implementation->getSelector(Selector);
1588 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.Value, SelID,
1589 IsInstanceMethod};
1590 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1591
1592 // If this method is a designated initializer, update the class to note that
1593 // it has designated initializers.
1594 if (Info.DesignatedInit) {
1595 assert(Implementation->ParentContexts.contains(CtxID.Value));
1596 uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
1597 ContextTableKey CtxKey(ParentCtxID,
1598 Implementation->ContextKinds[CtxID.Value],
1599 Implementation->ContextNames[CtxID.Value]);
1600 assert(Implementation->Contexts.contains(CtxKey));
1601 auto &VersionedVec = Implementation->Contexts[CtxKey].second;
1602 bool Found = false;
1603 for (auto &Versioned : VersionedVec) {
1604 if (Versioned.first == SwiftVersion) {
1605 Versioned.second.setHasDesignatedInits(true);
1606 Found = true;
1607 break;
1608 }
1609 }
1610
1611 if (!Found) {
1612 VersionedVec.push_back({SwiftVersion, ContextInfo()});
1613 VersionedVec.back().second.setHasDesignatedInits(true);
1614 }
1615 }
1616}
1617
1618void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
1619 const CXXMethodInfo &Info,
1620 VersionTuple SwiftVersion) {
1621 FunctionTableKey Key = Implementation->getFunctionKey(CtxID.Value, Name);
1622 Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
1623}
1624
1625void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name,
1627 const CXXMethodInfo &Info,
1628 VersionTuple SwiftVersion) {
1629 FunctionTableKey Key =
1630 Implementation->getFunctionKey(CtxID.Value, Name, Parameters);
1631 Implementation->CXXMethods[Key].push_back({SwiftVersion, Info});
1632}
1633
1634void APINotesWriter::addField(ContextID CtxID, llvm::StringRef Name,
1635 const FieldInfo &Info,
1636 VersionTuple SwiftVersion) {
1637 IdentifierID NameID = Implementation->getIdentifier(Name);
1638 SingleDeclTableKey Key(CtxID.Value, NameID);
1639 Implementation->Fields[Key].push_back({SwiftVersion, Info});
1640}
1641
1642void APINotesWriter::addGlobalVariable(std::optional<Context> Ctx,
1643 llvm::StringRef Name,
1644 const GlobalVariableInfo &Info,
1645 VersionTuple SwiftVersion) {
1646 IdentifierID VariableID = Implementation->getIdentifier(Name);
1647 SingleDeclTableKey Key(Ctx, VariableID);
1648 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1649}
1650
1651void APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
1652 llvm::StringRef Name,
1653 const GlobalFunctionInfo &Info,
1654 VersionTuple SwiftVersion) {
1655 FunctionTableKey Key = Implementation->getFunctionKey(Ctx, Name);
1656 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1657}
1658
1660 std::optional<Context> Ctx, llvm::StringRef Name,
1661 llvm::ArrayRef<llvm::StringRef> Parameters, const GlobalFunctionInfo &Info,
1662 VersionTuple SwiftVersion) {
1663 FunctionTableKey Key = Implementation->getFunctionKey(Ctx, Name, Parameters);
1664 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1665}
1666
1667void APINotesWriter::addEnumConstant(llvm::StringRef Name,
1668 const EnumConstantInfo &Info,
1669 VersionTuple SwiftVersion) {
1670 IdentifierID EnumConstantID = Implementation->getIdentifier(Name);
1671 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1672}
1673
1674void APINotesWriter::addTag(std::optional<Context> Ctx, llvm::StringRef Name,
1675 const TagInfo &Info, VersionTuple SwiftVersion) {
1676 IdentifierID TagID = Implementation->getIdentifier(Name);
1677 SingleDeclTableKey Key(Ctx, TagID);
1678 Implementation->Tags[Key].push_back({SwiftVersion, Info});
1679}
1680
1681void APINotesWriter::addTypedef(std::optional<Context> Ctx,
1682 llvm::StringRef Name, const TypedefInfo &Info,
1683 VersionTuple SwiftVersion) {
1684 IdentifierID TypedefID = Implementation->getIdentifier(Name);
1685 SingleDeclTableKey Key(Ctx, TypedefID);
1686 Implementation->Typedefs[Key].push_back({SwiftVersion, Info});
1687}
1688} // namespace api_notes
1689} // namespace clang
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
Defines the clang::FileManager interface and associated types.
static void emitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
static void emitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl< uint64_t > &Record)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
static StringRef getIdentifier(const Token &Tok)
#define BLOCK(DERIVED, BASE)
Definition Template.h:652
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
off_t getSize() const
Definition FileEntry.h:299
Smart pointer class that efficiently represents Objective-C method names.
Implementation(llvm::StringRef ModuleName, const FileEntry *SF)
void addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, bool IsInstanceMethod, const ObjCMethodInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C method.
void addEnumConstant(llvm::StringRef Name, const EnumConstantInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about an enumerator.
ContextID addContext(std::optional< ContextID > ParentCtxID, llvm::StringRef Name, ContextKind Kind, const ContextInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C class or protocol or a C++ namespace.
void addGlobalFunction(std::optional< Context > Ctx, llvm::StringRef Name, const GlobalFunctionInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a global function.
void addObjCProperty(ContextID CtxID, llvm::StringRef Name, bool IsInstanceProperty, const ObjCPropertyInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C property.
void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific C record field.
void addGlobalVariable(std::optional< Context > Ctx, llvm::StringRef Name, const GlobalVariableInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a global variable.
void addTypedef(std::optional< Context > Ctx, llvm::StringRef Name, const TypedefInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a typedef.
void writeToStream(llvm::raw_ostream &OS)
void addCXXMethod(ContextID CtxID, llvm::StringRef Name, const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific C++ method.
void addTag(std::optional< Context > Ctx, llvm::StringRef Name, const TagInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a tag (struct/union/enum/C++ class).
APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF)
Create a new API notes writer with the given module name and (optional) source file.
Describes API notes data for a C++ method.
Definition Types.h:803
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
Definition Types.h:970
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
Definition Types.h:235
Describes API notes data for an enumerator.
Definition Types.h:821
Describes API notes data for a C/C++ record field.
Definition Types.h:797
Describes API notes data for a global function.
Definition Types.h:791
Describes API notes data for a global variable.
Definition Types.h:785
Describes API notes data for an Objective-C method.
Definition Types.h:744
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Definition Types.h:748
Describes API notes data for an Objective-C property.
Definition Types.h:457
Describes API notes data for a tag.
Definition Types.h:827
Describes API notes data for a typedef.
Definition Types.h:938
llvm::BCRecordLayout< CONTEXT_INFO_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ContextInfoLayout
llvm::BCRecordLayout< CONTEXT_ID_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ContextIDLayout
llvm::BCRecordLayout< MODULE_NAME, llvm::BCBlob > ModuleNameLayout
llvm::BCRecordLayout< SOURCE_FILE, llvm::BCVBR< 16 >, llvm::BCVBR< 16 > > SourceFileLayout
llvm::BCRecordLayout< METADATA, llvm::BCFixed< 16 >, llvm::BCFixed< 16 > > MetadataLayout
llvm::BCRecordLayout< CXX_METHOD_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > CXXMethodDataLayout
llvm::BCRecordLayout< ENUM_CONSTANT_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > EnumConstantDataLayout
llvm::BCRecordLayout< FIELD_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > FieldDataLayout
llvm::BCRecordLayout< GLOBAL_FUNCTION_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > GlobalFunctionDataLayout
llvm::BCRecordLayout< GLOBAL_VARIABLE_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > GlobalVariableDataLayout
llvm::BCRecordLayout< IDENTIFIER_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > IdentifierDataLayout
llvm::BCRecordLayout< OBJC_METHOD_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ObjCMethodDataLayout
llvm::BCRecordLayout< OBJC_PROPERTY_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ObjCPropertyDataLayout
llvm::BCRecordLayout< OBJC_SELECTOR_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ObjCSelectorDataLayout
llvm::BCRecordLayout< TAG_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > TagDataLayout
llvm::BCRecordLayout< TYPEDEF_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > TypedefDataLayout
constexpr unsigned FunctionTableKeyBaseLength
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
llvm::PointerEmbeddedInt< unsigned, 31 > SelectorID
std::optional< FunctionTableKey > getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name, GetIdentifierFn GetIdentifier)
const uint8_t kSwiftConforms
const uint8_t kSwiftDoesNotConform
constexpr uint8_t FunctionKeyHasParameterSelector
A stored C or C++ function declaration, represented by the ID of its parent context,...
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...
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
uint32_t SelectorID
An ID number that refers to an ObjC selector in an AST file.
uint64_t TypeID
An ID number that refers to a type in an AST file.
Definition ASTBitCodes.h:88
unsigned ComputeHash(Selector Sel)
uint64_t IdentifierID
An ID number that refers to an identifier in an AST file.
Definition ASTBitCodes.h:63
std::shared_ptr< MatchComputation< T > > Generator
Definition RewriteRule.h:65
The JSON file list parser is used to communicate input to InstallAPI.
unsigned long uint64_t
hash_code hash_value(const clang::dependencies::ModuleID &ID)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 uint16_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
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:997
A stored Objective-C or C++ declaration, represented by the ID of its parent context,...