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"
26 using VersionedSmallVector =
29 std::string ModuleName;
36 llvm::StringMap<IdentifierID> IdentifierIDs;
45 std::pair<unsigned, VersionedSmallVector<ContextInfo>>>
51 llvm::DenseMap<uint32_t, uint32_t> ParentContexts;
54 llvm::DenseMap<unsigned, unsigned> ContextNames;
61 std::tuple<unsigned, unsigned, char>,
76 llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
88 llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
129 if (Identifier.empty())
133 return IdentifierIDs.try_emplace(Identifier, IdentifierIDs.size() + 1)
147 return SelectorIDs.try_emplace(
Selector, SelectorIDs.size()).first->second;
151 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
152 void writeControlBlock(llvm::BitstreamWriter &Stream);
153 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
154 void writeContextBlock(llvm::BitstreamWriter &Stream);
155 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
156 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
157 void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
158 void writeFieldBlock(llvm::BitstreamWriter &Stream);
159 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
160 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
161 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
162 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
163 void writeTagBlock(llvm::BitstreamWriter &Stream);
164 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
168 : ModuleName(
std::string(ModuleName)), SourceFile(SF) {}
177 llvm::BitstreamWriter Stream(Buffer);
181 Stream.Emit(Byte, 8);
184 writeBlockInfoBlock(Stream);
185 writeControlBlock(Stream);
186 writeIdentifierBlock(Stream);
187 writeContextBlock(Stream);
188 writeObjCPropertyBlock(Stream);
189 writeObjCMethodBlock(Stream);
190 writeCXXMethodBlock(Stream);
191 writeFieldBlock(Stream);
192 writeObjCSelectorBlock(Stream);
193 writeGlobalVariableBlock(Stream);
194 writeGlobalFunctionBlock(Stream);
195 writeEnumConstantBlock(Stream);
196 writeTagBlock(Stream);
197 writeTypedefBlock(Stream);
200 OS.write(Buffer.data(), Buffer.size());
206void emitBlockID(llvm::BitstreamWriter &Stream,
unsigned ID,
207 llvm::StringRef Name) {
208 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
215 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
217 const_cast<unsigned char *
>(
218 reinterpret_cast<const unsigned char *
>(Name.data())),
223void emitRecordID(llvm::BitstreamWriter &Stream,
unsigned ID,
224 llvm::StringRef Name) {
225 assert(ID < 256 &&
"can't fit record ID in next to name");
228 Buffer.resize(Name.size() + 1);
230 memcpy(Buffer.data() + 1, Name.data(), Name.size());
232 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
236void APINotesWriter::Implementation::writeBlockInfoBlock(
237 llvm::BitstreamWriter &Stream) {
238 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
240#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
241#define BLOCK_RECORD(NameSpace, Block) \
242 emitRecordID(Stream, NameSpace::Block, #Block)
243 BLOCK(CONTROL_BLOCK);
247 BLOCK(IDENTIFIER_BLOCK);
250 BLOCK(OBJC_CONTEXT_BLOCK);
253 BLOCK(OBJC_PROPERTY_BLOCK);
256 BLOCK(OBJC_METHOD_BLOCK);
259 BLOCK(OBJC_SELECTOR_BLOCK);
262 BLOCK(GLOBAL_VARIABLE_BLOCK);
263 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
265 BLOCK(GLOBAL_FUNCTION_BLOCK);
266 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
271void APINotesWriter::Implementation::writeControlBlock(
272 llvm::BitstreamWriter &Stream) {
279 ModuleName.emit(Scratch, this->ModuleName);
283 SourceFile.emit(Scratch, this->SourceFile->
getSize(),
284 this->SourceFile->getModificationTime());
290class IdentifierTableInfo {
292 using key_type = StringRef;
293 using key_type_ref = key_type;
295 using data_type_ref =
const data_type &;
297 using offset_type = unsigned;
299 hash_value_type
ComputeHash(key_type_ref Key) {
return llvm::djbHash(Key); }
301 std::pair<unsigned, unsigned>
302 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
306 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
307 writer.write<uint16_t>(KeyLength);
308 writer.write<uint16_t>(DataLength);
309 return {KeyLength, DataLength};
312 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
OS << Key; }
314 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
315 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
321void APINotesWriter::Implementation::writeIdentifierBlock(
322 llvm::BitstreamWriter &Stream) {
325 if (IdentifierIDs.empty())
328 llvm::SmallString<4096> HashTableBlob;
331 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo>
Generator;
332 for (
auto &II : IdentifierIDs)
335 llvm::raw_svector_ostream BlobStream(HashTableBlob);
337 llvm::support::endian::write<uint32_t>(BlobStream, 0,
338 llvm::endianness::little);
343 IdentifierData.emit(Scratch, Offset, HashTableBlob);
348class ContextIDTableInfo {
350 using key_type = ContextTableKey;
351 using key_type_ref = key_type;
352 using data_type = unsigned;
353 using data_type_ref =
const data_type &;
354 using hash_value_type =
size_t;
355 using offset_type = unsigned;
358 return static_cast<size_t>(Key.hashValue());
361 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
366 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
367 writer.write<uint16_t>(KeyLength);
368 writer.write<uint16_t>(DataLength);
369 return {KeyLength, DataLength};
372 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
373 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
374 writer.write<
uint32_t>(Key.parentContextID);
375 writer.write<uint8_t>(Key.contextKind);
376 writer.write<
uint32_t>(Key.contextID);
379 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
380 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
387template <
typename T>
struct MakeDependent {
typedef T Type; };
391unsigned getVersionTupleSize(
const VersionTuple &VT) {
392 unsigned size =
sizeof(uint8_t) +
sizeof(uint32_t);
395 if (VT.getSubminor())
404unsigned getVersionedInfoSize(
405 const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI,
406 llvm::function_ref<
unsigned(
const typename MakeDependent<T>::Type &)>
408 unsigned result =
sizeof(uint16_t);
409 for (
const auto &E : VI) {
410 result += getVersionTupleSize(E.first);
411 result += getInfoSize(E.second);
417void emitVersionTuple(raw_ostream &OS,
const VersionTuple &VT) {
418 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
424 else if (VT.getSubminor())
426 else if (VT.getMinor())
430 writer.write<uint8_t>(descriptor);
433 writer.write<
uint32_t>(VT.getMajor());
434 if (
auto minor = VT.getMinor())
436 if (
auto subminor = VT.getSubminor())
438 if (
auto build = VT.getBuild())
444void emitVersionedInfo(
445 raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI,
446 llvm::function_ref<
void(raw_ostream &,
447 const typename MakeDependent<T>::Type &)>
449 std::sort(VI.begin(), VI.end(),
450 [](
const std::pair<VersionTuple, T> &LHS,
451 const std::pair<VersionTuple, T> &RHS) ->
bool {
452 assert((&LHS == &RHS || LHS.first != RHS.first) &&
453 "two entries for the same version");
454 return LHS.first < RHS.first;
457 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
458 writer.write<uint16_t>(VI.size());
459 for (
const auto &E : VI) {
460 emitVersionTuple(OS, E.first);
461 emitInfo(OS, E.second);
466template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
467class VersionedTableInfo {
468 Derived &asDerived() {
return *
static_cast<Derived *
>(
this); }
470 const Derived &asDerived()
const {
471 return *
static_cast<const Derived *
>(
this);
475 using key_type = KeyType;
476 using key_type_ref = key_type;
478 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
479 using data_type_ref = data_type &;
480 using hash_value_type =
size_t;
481 using offset_type = unsigned;
483 std::pair<unsigned, unsigned>
484 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) {
485 uint32_t KeyLength = asDerived().getKeyLength(Key);
487 getVersionedInfoSize(Data, [
this](
const UnversionedDataType &UI) {
488 return asDerived().getUnversionedInfoSize(UI);
491 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
492 writer.write<uint16_t>(KeyLength);
493 writer.write<uint16_t>(DataLength);
494 return {KeyLength, DataLength};
497 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
499 OS, Data, [
this](llvm::raw_ostream &OS,
const UnversionedDataType &UI) {
500 asDerived().emitUnversionedInfo(OS, UI);
506void emitCommonEntityInfo(raw_ostream &OS,
const CommonEntityInfo &CEI) {
507 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
510 if (
auto safety = CEI.getSwiftSafety()) {
511 payload =
static_cast<unsigned>(*safety);
516 if (
auto swiftPrivate = CEI.isSwiftPrivate()) {
522 payload |= CEI.Unavailable;
524 payload |= CEI.UnavailableInSwift;
526 writer.write<uint8_t>(payload);
528 writer.write<uint16_t>(CEI.UnavailableMsg.size());
529 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
531 writer.write<uint16_t>(CEI.SwiftName.size());
532 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
537unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
538 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
543unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
544 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
545 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
546 (CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
547 getCommonEntityInfoSize(CTI);
551void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
552 emitCommonEntityInfo(OS, CTI);
554 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
555 if (
auto swiftBridge = CTI.getSwiftBridge()) {
556 writer.write<uint16_t>(swiftBridge->size() + 1);
557 OS.write(swiftBridge->c_str(), swiftBridge->size());
559 writer.write<uint16_t>(0);
561 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
562 writer.write<uint16_t>(nsErrorDomain->size() + 1);
563 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
565 writer.write<uint16_t>(0);
567 if (
auto conformance = CTI.getSwiftConformance()) {
568 writer.write<uint16_t>(conformance->size() + 1);
569 OS.write(conformance->c_str(), conformance->size());
571 writer.write<uint16_t>(0);
576class ContextInfoTableInfo
577 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
579 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
581 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
582 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
590 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
591 return getCommonTypeInfoSize(OCI) + 1;
594 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
595 emitCommonTypeInfo(OS, OCI);
598 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
599 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
601 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
602 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
604 if (
auto nullable = OCI.getDefaultNullability())
605 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
606 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
613void APINotesWriter::Implementation::writeContextBlock(
614 llvm::BitstreamWriter &Stream) {
617 if (Contexts.empty())
621 llvm::SmallString<4096> HashTableBlob;
624 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
625 for (
auto &OC : Contexts)
626 Generator.insert(OC.first, OC.second.first);
628 llvm::raw_svector_ostream BlobStream(HashTableBlob);
630 llvm::support::endian::write<uint32_t>(BlobStream, 0,
631 llvm::endianness::little);
636 ContextID.emit(Scratch, Offset, HashTableBlob);
640 llvm::SmallString<4096> HashTableBlob;
643 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
644 for (
auto &OC : Contexts)
645 Generator.insert(OC.second.first, OC.second.second);
647 llvm::raw_svector_ostream BlobStream(HashTableBlob);
649 llvm::support::endian::write<uint32_t>(BlobStream, 0,
650 llvm::endianness::little);
655 ContextInfo.emit(Scratch, Offset, HashTableBlob);
662unsigned getVariableInfoSize(
const VariableInfo &VI) {
663 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
665unsigned getParamInfoSize(
const ParamInfo &PI);
668void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
669 emitCommonEntityInfo(OS, VI);
671 uint8_t
bytes[2] = {0, 0};
672 if (
auto nullable = VI.getNullability()) {
674 bytes[1] =
static_cast<uint8_t
>(*nullable);
679 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
681 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
682 writer.write<uint16_t>(VI.getType().size());
683 OS.write(VI.getType().data(), VI.getType().size());
687class ObjCPropertyTableInfo
688 :
public VersionedTableInfo<ObjCPropertyTableInfo,
689 std::tuple<unsigned, unsigned, char>,
692 unsigned getKeyLength(key_type_ref) {
693 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
696 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
697 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
698 writer.write<
uint32_t>(std::get<0>(Key));
699 writer.write<
uint32_t>(std::get<1>(Key));
700 writer.write<uint8_t>(std::get<2>(Key));
707 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
708 return getVariableInfoSize(OPI) + 1;
711 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
712 emitVariableInfo(OS, OPI);
715 if (
auto value = OPI.getSwiftImportAsAccessors()) {
717 flags |= value.value() << 1;
724void APINotesWriter::Implementation::writeObjCPropertyBlock(
725 llvm::BitstreamWriter &Stream) {
728 if (ObjCProperties.empty())
732 llvm::SmallString<4096> HashTableBlob;
735 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
736 for (
auto &OP : ObjCProperties)
739 llvm::raw_svector_ostream BlobStream(HashTableBlob);
741 llvm::support::endian::write<uint32_t>(BlobStream, 0,
742 llvm::endianness::little);
747 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
752unsigned getFunctionInfoSize(
const FunctionInfo &);
753void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
754void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI);
757class ObjCMethodTableInfo
758 :
public VersionedTableInfo<ObjCMethodTableInfo,
759 std::tuple<unsigned, unsigned, char>,
762 unsigned getKeyLength(key_type_ref) {
763 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
766 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
767 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
768 writer.write<
uint32_t>(std::get<0>(Key));
769 writer.write<
uint32_t>(std::get<1>(Key));
770 writer.write<uint8_t>(std::get<2>(Key));
777 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
778 auto size = getFunctionInfoSize(OMI) + 1;
780 size += getParamInfoSize(*OMI.Self);
784 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
786 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
787 flags = (flags << 1) | OMI.DesignatedInit;
788 flags = (flags << 1) | OMI.RequiredInit;
789 flags = (flags << 1) | static_cast<bool>(OMI.Self);
790 writer.write<uint8_t>(flags);
792 emitFunctionInfo(OS, OMI);
795 emitParamInfo(OS, *OMI.Self);
800class CXXMethodTableInfo
801 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
804 unsigned getKeyLength(key_type_ref) {
805 return sizeof(
uint32_t) +
sizeof(uint32_t);
808 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
809 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
810 writer.write<
uint32_t>(Key.parentContextID);
815 return static_cast<size_t>(key.hashValue());
818 unsigned getUnversionedInfoSize(
const CXXMethodInfo &MI) {
819 auto size = getFunctionInfoSize(MI) + 1;
821 size += getParamInfoSize(*MI.This);
825 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &MI) {
827 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
828 flags = (flags << 1) | static_cast<bool>(MI.This);
829 writer.write<uint8_t>(flags);
831 emitFunctionInfo(OS, MI);
833 emitParamInfo(OS, *MI.This);
838void APINotesWriter::Implementation::writeObjCMethodBlock(
839 llvm::BitstreamWriter &Stream) {
842 if (ObjCMethods.empty())
846 llvm::SmallString<4096> HashTableBlob;
849 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
850 for (
auto &OM : ObjCMethods)
853 llvm::raw_svector_ostream BlobStream(HashTableBlob);
855 llvm::support::endian::write<uint32_t>(BlobStream, 0,
856 llvm::endianness::little);
861 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
865void APINotesWriter::Implementation::writeCXXMethodBlock(
866 llvm::BitstreamWriter &Stream) {
869 if (CXXMethods.empty())
873 llvm::SmallString<4096> HashTableBlob;
876 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
877 for (
auto &MD : CXXMethods)
880 llvm::raw_svector_ostream BlobStream(HashTableBlob);
882 llvm::support::endian::write<uint32_t>(BlobStream, 0,
883 llvm::endianness::little);
888 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
895 :
public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
897 unsigned getKeyLength(key_type_ref) {
898 return sizeof(
uint32_t) +
sizeof(uint32_t);
901 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
902 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
903 writer.write<
uint32_t>(Key.parentContextID);
908 return static_cast<size_t>(key.hashValue());
911 unsigned getUnversionedInfoSize(
const FieldInfo &FI) {
912 return getVariableInfoSize(FI);
915 void emitUnversionedInfo(raw_ostream &OS,
const FieldInfo &FI) {
916 emitVariableInfo(OS, FI);
921void APINotesWriter::Implementation::writeFieldBlock(
922 llvm::BitstreamWriter &Stream) {
929 llvm::SmallString<4096> HashTableBlob;
932 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo>
Generator;
933 for (
auto &FD : Fields)
936 llvm::raw_svector_ostream BlobStream(HashTableBlob);
938 llvm::support::endian::write<uint32_t>(BlobStream, 0,
939 llvm::endianness::little);
944 FieldData.emit(Scratch, Offset, HashTableBlob);
950class ObjCSelectorTableInfo {
952 using key_type = StoredObjCSelector;
953 using key_type_ref =
const key_type &;
955 using data_type_ref = data_type;
956 using hash_value_type = unsigned;
957 using offset_type = unsigned;
960 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
963 std::pair<unsigned, unsigned>
964 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
966 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
969 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
970 writer.write<uint16_t>(KeyLength);
971 writer.write<uint16_t>(DataLength);
972 return {KeyLength, DataLength};
975 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
976 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
977 writer.write<uint16_t>(Key.NumArgs);
978 for (
auto Identifier : Key.Identifiers)
982 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
983 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
989void APINotesWriter::Implementation::writeObjCSelectorBlock(
990 llvm::BitstreamWriter &Stream) {
993 if (SelectorIDs.empty())
997 llvm::SmallString<4096> HashTableBlob;
1000 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
1001 for (
auto &S : SelectorIDs)
1004 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1006 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1007 llvm::endianness::little);
1012 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
1018class GlobalVariableTableInfo
1019 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
1020 GlobalVariableInfo> {
1022 unsigned getKeyLength(key_type_ref) {
1023 return sizeof(
uint32_t) +
sizeof(uint32_t);
1026 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1027 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1028 writer.write<
uint32_t>(Key.parentContextID);
1029 writer.write<
uint32_t>(Key.nameID);
1033 return static_cast<size_t>(Key.hashValue());
1036 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
1037 return getVariableInfoSize(GVI);
1040 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
1041 emitVariableInfo(OS, GVI);
1046void APINotesWriter::Implementation::writeGlobalVariableBlock(
1047 llvm::BitstreamWriter &Stream) {
1050 if (GlobalVariables.empty())
1054 llvm::SmallString<4096> HashTableBlob;
1057 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
1058 for (
auto &GV : GlobalVariables)
1061 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1063 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1064 llvm::endianness::little);
1069 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1074unsigned getParamInfoSize(
const ParamInfo &PI) {
1075 return getVariableInfoSize(PI) + 1;
1078void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
1079 emitVariableInfo(OS, PI);
1082 if (
auto noescape = PI.isNoEscape()) {
1088 if (
auto lifetimebound = PI.isLifetimebound()) {
1094 if (
auto RCC = PI.getRetainCountConvention())
1095 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1097 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1098 writer.write<uint8_t>(flags);
1103unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1104 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1105 size +=
sizeof(uint16_t);
1106 for (
const auto &P : FI.Params)
1107 size += getParamInfoSize(P);
1108 size +=
sizeof(uint16_t) + FI.ResultType.size();
1109 size +=
sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
1114void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1115 emitCommonEntityInfo(OS, FI);
1118 flags |= FI.NullabilityAudited;
1120 if (
auto RCC = FI.getRetainCountConvention())
1121 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1123 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1125 writer.write<uint8_t>(flags);
1126 writer.write<uint8_t>(FI.NumAdjustedNullable);
1127 writer.write<
uint64_t>(FI.NullabilityPayload);
1129 writer.write<uint16_t>(FI.Params.size());
1130 for (
const auto &PI : FI.Params)
1131 emitParamInfo(OS, PI);
1133 writer.write<uint16_t>(FI.ResultType.size());
1134 writer.write(ArrayRef<char>{FI.ResultType});
1135 writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1136 writer.write(ArrayRef<char>{FI.SwiftReturnOwnership});
1140class GlobalFunctionTableInfo
1141 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1142 GlobalFunctionInfo> {
1144 unsigned getKeyLength(key_type_ref) {
1145 return sizeof(
uint32_t) +
sizeof(uint32_t);
1148 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1149 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1150 writer.write<
uint32_t>(Key.parentContextID);
1151 writer.write<
uint32_t>(Key.nameID);
1155 return static_cast<size_t>(Key.hashValue());
1158 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1159 return getFunctionInfoSize(GFI);
1162 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1163 emitFunctionInfo(OS, GFI);
1168void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1169 llvm::BitstreamWriter &Stream) {
1172 if (GlobalFunctions.empty())
1176 llvm::SmallString<4096> HashTableBlob;
1179 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1180 for (
auto &F : GlobalFunctions)
1183 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1185 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1186 llvm::endianness::little);
1191 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1197class EnumConstantTableInfo
1198 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1201 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
1203 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1204 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1212 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1213 return getCommonEntityInfoSize(ECI);
1216 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1217 emitCommonEntityInfo(OS, ECI);
1222void APINotesWriter::Implementation::writeEnumConstantBlock(
1223 llvm::BitstreamWriter &Stream) {
1226 if (EnumConstants.empty())
1230 llvm::SmallString<4096> HashTableBlob;
1233 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1234 for (
auto &EC : EnumConstants)
1237 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1239 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1240 llvm::endianness::little);
1245 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1250template <
typename Derived,
typename UnversionedDataType>
1251class CommonTypeTableInfo
1252 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1253 UnversionedDataType> {
1255 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1256 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1258 unsigned getKeyLength(key_type_ref) {
1259 return sizeof(
uint32_t) +
sizeof(IdentifierID);
1262 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1263 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1264 writer.write<
uint32_t>(Key.parentContextID);
1269 return static_cast<size_t>(Key.hashValue());
1272 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1273 return getCommonTypeInfoSize(UDT);
1276 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1277 emitCommonTypeInfo(OS, UDT);
1282class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1284 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1286 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1287 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1288 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1289 2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
1290 2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1291 3 + getCommonTypeInfoSize(TI);
1295 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1296 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1299 if (
auto extensibility = TI.EnumExtensibility) {
1300 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1301 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1305 if (
auto value = TI.isFlagEnum())
1306 Flags |= (value.value() << 1 | 1 << 0);
1308 writer.write<uint8_t>(Flags);
1310 if (
auto Copyable = TI.isSwiftCopyable())
1313 writer.write<uint8_t>(0);
1315 if (
auto Escapable = TI.isSwiftEscapable())
1318 writer.write<uint8_t>(0);
1320 if (
auto ImportAs = TI.SwiftImportAs) {
1321 writer.write<uint16_t>(ImportAs->size() + 1);
1322 OS.write(ImportAs->c_str(), ImportAs->size());
1324 writer.write<uint16_t>(0);
1326 if (
auto RetainOp = TI.SwiftRetainOp) {
1327 writer.write<uint16_t>(RetainOp->size() + 1);
1328 OS.write(RetainOp->c_str(), RetainOp->size());
1330 writer.write<uint16_t>(0);
1332 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1333 writer.write<uint16_t>(ReleaseOp->size() + 1);
1334 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1336 writer.write<uint16_t>(0);
1338 if (
auto DefaultOwnership = TI.SwiftDefaultOwnership) {
1339 writer.write<uint16_t>(DefaultOwnership->size() + 1);
1340 OS.write(DefaultOwnership->c_str(), DefaultOwnership->size());
1342 writer.write<uint16_t>(0);
1344 if (
auto DestroyOp = TI.SwiftDestroyOp) {
1345 writer.write<uint16_t>(DestroyOp->size() + 1);
1346 OS.write(DestroyOp->c_str(), DestroyOp->size());
1348 writer.write<uint16_t>(0);
1351 emitCommonTypeInfo(OS, TI);
1356void APINotesWriter::Implementation::writeTagBlock(
1357 llvm::BitstreamWriter &Stream) {
1364 llvm::SmallString<4096> HashTableBlob;
1367 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1368 for (
auto &
T : Tags)
1371 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1373 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1374 llvm::endianness::little);
1379 TagData.emit(Scratch, Offset, HashTableBlob);
1385class TypedefTableInfo
1386 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1388 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1389 return 1 + getCommonTypeInfoSize(TI);
1392 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1393 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1396 if (
auto swiftWrapper = TI.SwiftWrapper)
1397 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1399 writer.write<uint8_t>(Flags);
1401 emitCommonTypeInfo(OS, TI);
1406void APINotesWriter::Implementation::writeTypedefBlock(
1407 llvm::BitstreamWriter &Stream) {
1410 if (Typedefs.empty())
1414 llvm::SmallString<4096> HashTableBlob;
1417 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1418 for (
auto &
T : Typedefs)
1421 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1423 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1424 llvm::endianness::little);
1429 TypedefData.emit(Scratch, Offset, HashTableBlob);
1447 llvm::VersionTuple SwiftVersion) {
1450 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1451 ContextTableKey Key(RawParentCtxID,
static_cast<uint8_t
>(Kind), NameID);
1456 Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
1458 .insert(std::make_pair(
1459 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1467 auto &VersionedVec = Known->second.second;
1469 for (
auto &Versioned : VersionedVec) {
1470 if (Versioned.first == SwiftVersion) {
1471 Versioned.second |= Info;
1478 VersionedVec.push_back({SwiftVersion, Info});
1484 bool IsInstanceProperty,
1486 VersionTuple SwiftVersion) {
1489 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1490 .push_back({SwiftVersion, Info});
1494 bool IsInstanceMethod,
1496 VersionTuple SwiftVersion) {
1498 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1500 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1513 for (
auto &Versioned : VersionedVec) {
1514 if (Versioned.first == SwiftVersion) {
1515 Versioned.second.setHasDesignatedInits(
true);
1522 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1523 VersionedVec.back().second.setHasDesignatedInits(
true);
1530 VersionTuple SwiftVersion) {
1538 VersionTuple SwiftVersion) {
1545 llvm::StringRef Name,
1547 VersionTuple SwiftVersion) {
1550 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1554 llvm::StringRef Name,
1556 VersionTuple SwiftVersion) {
1559 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1564 VersionTuple SwiftVersion) {
1566 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1570 const TagInfo &Info, VersionTuple SwiftVersion) {
1578 VersionTuple SwiftVersion) {
#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)
static StringRef getIdentifier(const Token &Tok)
#define BLOCK(DERIVED, BASE)
__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).
Smart pointer class that efficiently represents Objective-C method names.
friend class APINotesWriter
void writeToStream(llvm::raw_ostream &OS)
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.
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
Describes API notes data for an enumerator.
Describes API notes data for a C/C++ record field.
Describes API notes data for a global function.
Describes API notes data for a global variable.
Describes API notes data for an Objective-C method.
unsigned DesignatedInit
Whether this is a designated initializer of its class.
Describes API notes data for an Objective-C property.
Describes API notes data for a tag.
Describes API notes data for a typedef.
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
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
llvm::PointerEmbeddedInt< unsigned, 31 > SelectorID
const uint8_t kSwiftConforms
const uint8_t kSwiftDoesNotConform
const uint16_t VERSION_MAJOR
API notes file major version number.
const unsigned char API_NOTES_SIGNATURE[]
Magic number for API notes files.
const uint16_t VERSION_MINOR
API notes file minor version number.
@ OBJC_CONTEXT_BLOCK_ID
The Objective-C context data block, which contains information about Objective-C classes and protocol...
@ TYPEDEF_BLOCK_ID
The typedef data block, which maps typedef names to information about the typedefs.
@ OBJC_PROPERTY_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, property name) pairs to info...
@ ENUM_CONSTANT_BLOCK_ID
The enum constant data block, which maps enumerator names to information about the enumerators.
@ TAG_BLOCK_ID
The tag data block, which maps tag names to information about the tags.
@ OBJC_METHOD_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, selector,...
@ FIELD_BLOCK_ID
The fields data block, which maps names fields of C records to information about the field.
@ OBJC_SELECTOR_BLOCK_ID
The Objective-C selector data block, which maps Objective-C selector names (# of pieces,...
@ CXX_METHOD_BLOCK_ID
The C++ method data block, which maps C++ (context id, method name) pairs to information about the me...
@ GLOBAL_FUNCTION_BLOCK_ID
The (global) functions data block, which maps global function names to information about the global f...
@ CONTROL_BLOCK_ID
The control block, which contains all of the information that needs to be validated prior to committi...
@ IDENTIFIER_BLOCK_ID
The identifier data block, which maps identifier strings to IDs.
@ GLOBAL_VARIABLE_BLOCK_ID
The global variables data block, which maps global variable names to information about the global var...
@ 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.
unsigned ComputeHash(Selector Sel)
uint64_t IdentifierID
An ID number that refers to an identifier in an AST file.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
A stored Objective-C or C++ context, represented by the ID of its parent context, the kind of this co...
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
llvm::ArrayRef< llvm::StringRef > Identifiers
A stored Objective-C or C++ declaration, represented by the ID of its parent context,...
A stored Objective-C selector.