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"
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;
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());
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())),
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 &;
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())
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;
353 using data_type_ref =
const data_type &;
354 using hash_value_type =
size_t;
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);
394 size +=
sizeof(uint32_t);
395 if (VT.getSubminor())
396 size +=
sizeof(uint32_t);
398 size +=
sizeof(uint32_t);
404unsigned getVersionedInfoSize(
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())
435 writer.write<uint32_t>(*minor);
436 if (
auto subminor = VT.getSubminor())
437 writer.write<uint32_t>(*subminor);
438 if (
auto build = VT.getBuild())
439 writer.write<uint32_t>(*build);
444void emitVersionedInfo(
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;
479 using data_type_ref = data_type &;
480 using hash_value_type =
size_t;
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 swiftPrivate = CEI.isSwiftPrivate()) {
516 payload |= CEI.Unavailable;
518 payload |= CEI.UnavailableInSwift;
520 writer.write<uint8_t>(payload);
522 writer.write<uint16_t>(CEI.UnavailableMsg.size());
523 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
525 writer.write<uint16_t>(CEI.SwiftName.size());
526 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
531unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
532 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
537unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
538 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
539 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
540 (CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
541 getCommonEntityInfoSize(CTI);
545void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
546 emitCommonEntityInfo(OS, CTI);
548 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
549 if (
auto swiftBridge = CTI.getSwiftBridge()) {
550 writer.write<uint16_t>(swiftBridge->size() + 1);
551 OS.write(swiftBridge->c_str(), swiftBridge->size());
553 writer.write<uint16_t>(0);
555 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
556 writer.write<uint16_t>(nsErrorDomain->size() + 1);
557 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
559 writer.write<uint16_t>(0);
561 if (
auto conformance = CTI.getSwiftConformance()) {
562 writer.write<uint16_t>(conformance->size() + 1);
563 OS.write(conformance->c_str(), conformance->size());
565 writer.write<uint16_t>(0);
570class ContextInfoTableInfo
571 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
573 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
575 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
576 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
584 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
585 return getCommonTypeInfoSize(OCI) + 1;
588 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
589 emitCommonTypeInfo(OS, OCI);
592 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
593 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
595 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
596 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
598 if (
auto nullable = OCI.getDefaultNullability())
599 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
600 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
607void APINotesWriter::Implementation::writeContextBlock(
608 llvm::BitstreamWriter &Stream) {
611 if (Contexts.empty())
618 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
619 for (
auto &OC : Contexts)
620 Generator.insert(OC.first, OC.second.first);
622 llvm::raw_svector_ostream BlobStream(HashTableBlob);
624 llvm::support::endian::write<uint32_t>(BlobStream, 0,
625 llvm::endianness::little);
630 ContextID.emit(Scratch, Offset, HashTableBlob);
637 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
638 for (
auto &OC : Contexts)
639 Generator.insert(OC.second.first, OC.second.second);
641 llvm::raw_svector_ostream BlobStream(HashTableBlob);
643 llvm::support::endian::write<uint32_t>(BlobStream, 0,
644 llvm::endianness::little);
649 ContextInfo.emit(Scratch, Offset, HashTableBlob);
656unsigned getVariableInfoSize(
const VariableInfo &VI) {
657 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
659unsigned getParamInfoSize(
const ParamInfo &PI);
662void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
663 emitCommonEntityInfo(OS, VI);
665 uint8_t
bytes[2] = {0, 0};
666 if (
auto nullable = VI.getNullability()) {
668 bytes[1] =
static_cast<uint8_t
>(*nullable);
673 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
675 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
676 writer.write<uint16_t>(VI.getType().size());
677 OS.write(VI.getType().data(), VI.getType().size());
681class ObjCPropertyTableInfo
682 :
public VersionedTableInfo<ObjCPropertyTableInfo,
683 std::tuple<unsigned, unsigned, char>,
686 unsigned getKeyLength(key_type_ref) {
687 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
690 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
691 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
692 writer.write<
uint32_t>(std::get<0>(Key));
693 writer.write<
uint32_t>(std::get<1>(Key));
694 writer.write<uint8_t>(std::get<2>(Key));
701 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
702 return getVariableInfoSize(OPI) + 1;
705 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
706 emitVariableInfo(OS, OPI);
709 if (
auto value = OPI.getSwiftImportAsAccessors()) {
711 flags |= value.value() << 1;
718void APINotesWriter::Implementation::writeObjCPropertyBlock(
719 llvm::BitstreamWriter &Stream) {
722 if (ObjCProperties.empty())
729 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
730 for (
auto &OP : ObjCProperties)
733 llvm::raw_svector_ostream BlobStream(HashTableBlob);
735 llvm::support::endian::write<uint32_t>(BlobStream, 0,
736 llvm::endianness::little);
741 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
746unsigned getFunctionInfoSize(
const FunctionInfo &);
747void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
748void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI);
751class ObjCMethodTableInfo
752 :
public VersionedTableInfo<ObjCMethodTableInfo,
753 std::tuple<unsigned, unsigned, char>,
756 unsigned getKeyLength(key_type_ref) {
757 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
760 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
761 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
762 writer.write<
uint32_t>(std::get<0>(Key));
763 writer.write<
uint32_t>(std::get<1>(Key));
764 writer.write<uint8_t>(std::get<2>(Key));
771 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
772 auto size = getFunctionInfoSize(OMI) + 1;
774 size += getParamInfoSize(*OMI.Self);
778 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
780 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
781 flags = (flags << 1) | OMI.DesignatedInit;
782 flags = (flags << 1) | OMI.RequiredInit;
783 flags = (flags << 1) | static_cast<bool>(OMI.Self);
784 writer.write<uint8_t>(flags);
786 emitFunctionInfo(OS, OMI);
789 emitParamInfo(OS, *OMI.Self);
794class CXXMethodTableInfo
795 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
798 unsigned getKeyLength(key_type_ref) {
799 return sizeof(
uint32_t) +
sizeof(uint32_t);
802 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
803 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
804 writer.write<
uint32_t>(Key.parentContextID);
809 return static_cast<size_t>(key.hashValue());
812 unsigned getUnversionedInfoSize(
const CXXMethodInfo &MI) {
813 auto size = getFunctionInfoSize(MI) + 1;
815 size += getParamInfoSize(*MI.This);
819 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &MI) {
821 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
822 flags = (flags << 1) | static_cast<bool>(MI.This);
823 writer.write<uint8_t>(flags);
825 emitFunctionInfo(OS, MI);
827 emitParamInfo(OS, *MI.This);
832void APINotesWriter::Implementation::writeObjCMethodBlock(
833 llvm::BitstreamWriter &Stream) {
836 if (ObjCMethods.empty())
843 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
844 for (
auto &OM : ObjCMethods)
847 llvm::raw_svector_ostream BlobStream(HashTableBlob);
849 llvm::support::endian::write<uint32_t>(BlobStream, 0,
850 llvm::endianness::little);
855 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
859void APINotesWriter::Implementation::writeCXXMethodBlock(
860 llvm::BitstreamWriter &Stream) {
863 if (CXXMethods.empty())
870 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
871 for (
auto &MD : CXXMethods)
874 llvm::raw_svector_ostream BlobStream(HashTableBlob);
876 llvm::support::endian::write<uint32_t>(BlobStream, 0,
877 llvm::endianness::little);
882 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
889 :
public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
891 unsigned getKeyLength(key_type_ref) {
892 return sizeof(
uint32_t) +
sizeof(uint32_t);
895 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
896 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
897 writer.write<
uint32_t>(Key.parentContextID);
902 return static_cast<size_t>(key.hashValue());
905 unsigned getUnversionedInfoSize(
const FieldInfo &FI) {
906 return getVariableInfoSize(FI);
909 void emitUnversionedInfo(raw_ostream &OS,
const FieldInfo &FI) {
910 emitVariableInfo(OS, FI);
915void APINotesWriter::Implementation::writeFieldBlock(
916 llvm::BitstreamWriter &Stream) {
926 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo>
Generator;
927 for (
auto &FD : Fields)
930 llvm::raw_svector_ostream BlobStream(HashTableBlob);
932 llvm::support::endian::write<uint32_t>(BlobStream, 0,
933 llvm::endianness::little);
938 FieldData.emit(Scratch, Offset, HashTableBlob);
944class ObjCSelectorTableInfo {
946 using key_type = StoredObjCSelector;
947 using key_type_ref =
const key_type &;
949 using data_type_ref = data_type;
954 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
957 std::pair<unsigned, unsigned>
958 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
960 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
963 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
964 writer.write<uint16_t>(KeyLength);
965 writer.write<uint16_t>(DataLength);
966 return {KeyLength, DataLength};
969 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
970 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
971 writer.write<uint16_t>(Key.NumArgs);
976 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
977 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
983void APINotesWriter::Implementation::writeObjCSelectorBlock(
984 llvm::BitstreamWriter &Stream) {
987 if (SelectorIDs.empty())
994 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
995 for (
auto &S : SelectorIDs)
998 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1000 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1001 llvm::endianness::little);
1006 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
1012class GlobalVariableTableInfo
1013 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
1014 GlobalVariableInfo> {
1016 unsigned getKeyLength(key_type_ref) {
1017 return sizeof(
uint32_t) +
sizeof(uint32_t);
1020 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1021 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1022 writer.write<
uint32_t>(Key.parentContextID);
1023 writer.write<
uint32_t>(Key.nameID);
1027 return static_cast<size_t>(Key.hashValue());
1030 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
1031 return getVariableInfoSize(GVI);
1034 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
1035 emitVariableInfo(OS, GVI);
1040void APINotesWriter::Implementation::writeGlobalVariableBlock(
1041 llvm::BitstreamWriter &Stream) {
1044 if (GlobalVariables.empty())
1051 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
1052 for (
auto &GV : GlobalVariables)
1055 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1057 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1058 llvm::endianness::little);
1063 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1068unsigned getParamInfoSize(
const ParamInfo &PI) {
1069 return getVariableInfoSize(PI) + 1;
1072void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
1073 emitVariableInfo(OS, PI);
1076 if (
auto noescape = PI.isNoEscape()) {
1082 if (
auto lifetimebound = PI.isLifetimebound()) {
1088 if (
auto RCC = PI.getRetainCountConvention())
1089 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1091 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1092 writer.write<uint8_t>(flags);
1097unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1098 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1099 size +=
sizeof(uint16_t);
1100 for (
const auto &
P : FI.Params)
1101 size += getParamInfoSize(
P);
1102 size +=
sizeof(uint16_t) + FI.ResultType.size();
1103 size +=
sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
1108void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1109 emitCommonEntityInfo(OS, FI);
1112 flags |= FI.NullabilityAudited;
1114 if (
auto RCC = FI.getRetainCountConvention())
1115 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1117 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1119 writer.write<uint8_t>(flags);
1120 writer.write<uint8_t>(FI.NumAdjustedNullable);
1121 writer.write<
uint64_t>(FI.NullabilityPayload);
1123 writer.write<uint16_t>(FI.Params.size());
1124 for (
const auto &PI : FI.Params)
1125 emitParamInfo(OS, PI);
1127 writer.write<uint16_t>(FI.ResultType.size());
1128 writer.write(ArrayRef<char>{FI.ResultType});
1129 writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1130 writer.write(ArrayRef<char>{FI.SwiftReturnOwnership});
1134class GlobalFunctionTableInfo
1135 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1136 GlobalFunctionInfo> {
1138 unsigned getKeyLength(key_type_ref) {
1139 return sizeof(
uint32_t) +
sizeof(uint32_t);
1142 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1143 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1144 writer.write<
uint32_t>(Key.parentContextID);
1145 writer.write<
uint32_t>(Key.nameID);
1149 return static_cast<size_t>(Key.hashValue());
1152 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1153 return getFunctionInfoSize(GFI);
1156 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1157 emitFunctionInfo(OS, GFI);
1162void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1163 llvm::BitstreamWriter &Stream) {
1166 if (GlobalFunctions.empty())
1173 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1174 for (
auto &F : GlobalFunctions)
1177 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1179 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1180 llvm::endianness::little);
1185 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1191class EnumConstantTableInfo
1192 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1195 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
1197 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1198 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1206 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1207 return getCommonEntityInfoSize(ECI);
1210 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1211 emitCommonEntityInfo(OS, ECI);
1216void APINotesWriter::Implementation::writeEnumConstantBlock(
1217 llvm::BitstreamWriter &Stream) {
1220 if (EnumConstants.empty())
1227 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1228 for (
auto &EC : EnumConstants)
1231 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1233 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1234 llvm::endianness::little);
1239 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1244template <
typename Derived,
typename UnversionedDataType>
1245class CommonTypeTableInfo
1246 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1247 UnversionedDataType> {
1249 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1250 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1252 unsigned getKeyLength(key_type_ref) {
1253 return sizeof(
uint32_t) +
sizeof(IdentifierID);
1256 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1257 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1258 writer.write<
uint32_t>(Key.parentContextID);
1263 return static_cast<size_t>(Key.hashValue());
1266 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1267 return getCommonTypeInfoSize(UDT);
1270 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1271 emitCommonTypeInfo(OS, UDT);
1276class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1278 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1280 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1281 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1282 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1283 2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
1284 2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1285 3 + getCommonTypeInfoSize(TI);
1289 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1290 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1293 if (
auto extensibility = TI.EnumExtensibility) {
1294 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1295 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1299 if (
auto value = TI.isFlagEnum())
1300 Flags |= (value.value() << 1 | 1 << 0);
1302 writer.write<uint8_t>(Flags);
1304 if (
auto Copyable = TI.isSwiftCopyable())
1305 writer.write<uint8_t>(*Copyable ? kSwiftConforms : kSwiftDoesNotConform);
1307 writer.write<uint8_t>(0);
1309 if (
auto Escapable = TI.isSwiftEscapable())
1310 writer.write<uint8_t>(*Escapable ? kSwiftConforms : kSwiftDoesNotConform);
1312 writer.write<uint8_t>(0);
1314 if (
auto ImportAs = TI.SwiftImportAs) {
1315 writer.write<uint16_t>(ImportAs->size() + 1);
1316 OS.write(ImportAs->c_str(), ImportAs->size());
1318 writer.write<uint16_t>(0);
1320 if (
auto RetainOp = TI.SwiftRetainOp) {
1321 writer.write<uint16_t>(RetainOp->size() + 1);
1322 OS.write(RetainOp->c_str(), RetainOp->size());
1324 writer.write<uint16_t>(0);
1326 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1327 writer.write<uint16_t>(ReleaseOp->size() + 1);
1328 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1330 writer.write<uint16_t>(0);
1332 if (
auto DefaultOwnership = TI.SwiftDefaultOwnership) {
1333 writer.write<uint16_t>(DefaultOwnership->size() + 1);
1334 OS.write(DefaultOwnership->c_str(), DefaultOwnership->size());
1336 writer.write<uint16_t>(0);
1338 if (
auto DestroyOp = TI.SwiftDestroyOp) {
1339 writer.write<uint16_t>(DestroyOp->size() + 1);
1340 OS.write(DestroyOp->c_str(), DestroyOp->size());
1342 writer.write<uint16_t>(0);
1345 emitCommonTypeInfo(OS, TI);
1350void APINotesWriter::Implementation::writeTagBlock(
1351 llvm::BitstreamWriter &Stream) {
1361 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1362 for (
auto &
T : Tags)
1365 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1367 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1368 llvm::endianness::little);
1373 TagData.emit(Scratch, Offset, HashTableBlob);
1379class TypedefTableInfo
1380 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1382 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1383 return 1 + getCommonTypeInfoSize(TI);
1386 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1387 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1390 if (
auto swiftWrapper = TI.SwiftWrapper)
1391 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1393 writer.write<uint8_t>(Flags);
1395 emitCommonTypeInfo(OS, TI);
1400void APINotesWriter::Implementation::writeTypedefBlock(
1401 llvm::BitstreamWriter &Stream) {
1404 if (Typedefs.empty())
1411 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1412 for (
auto &
T : Typedefs)
1415 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1417 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1418 llvm::endianness::little);
1423 TypedefData.emit(Scratch, Offset, HashTableBlob);
1441 llvm::VersionTuple SwiftVersion) {
1444 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1452 .insert(std::make_pair(
1453 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1461 auto &VersionedVec = Known->second.second;
1463 for (
auto &Versioned : VersionedVec) {
1464 if (Versioned.first == SwiftVersion) {
1465 Versioned.second |= Info;
1472 VersionedVec.push_back({SwiftVersion, Info});
1478 bool IsInstanceProperty,
1480 VersionTuple SwiftVersion) {
1483 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1484 .push_back({SwiftVersion, Info});
1488 bool IsInstanceMethod,
1490 VersionTuple SwiftVersion) {
1492 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1494 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1507 for (
auto &Versioned : VersionedVec) {
1508 if (Versioned.first == SwiftVersion) {
1509 Versioned.second.setHasDesignatedInits(
true);
1516 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1517 VersionedVec.back().second.setHasDesignatedInits(
true);
1524 VersionTuple SwiftVersion) {
1532 VersionTuple SwiftVersion) {
1539 llvm::StringRef Name,
1541 VersionTuple SwiftVersion) {
1544 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1548 llvm::StringRef Name,
1550 VersionTuple SwiftVersion) {
1553 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1558 VersionTuple SwiftVersion) {
1560 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1564 const TagInfo &Info, VersionTuple SwiftVersion) {
1572 VersionTuple SwiftVersion) {
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
enum clang::sema::@1840::IndirectLocalPathEntry::EntryKind Kind
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)
Cached information about one file (either on disk or in the virtual file system).
Smart pointer class that efficiently represents Objective-C method names.
void writeToStream(llvm::raw_ostream &OS)
Implementation(llvm::StringRef ModuleName, const FileEntry *SF)
A class that writes API notes data to a binary representation that can be read by the APINotesReader.
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_ID_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ContextIDLayout
llvm::BCRecordLayout< CONTEXT_INFO_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ContextInfoLayout
llvm::BCRecordLayout< SOURCE_FILE, llvm::BCVBR< 16 >, llvm::BCVBR< 16 > > SourceFileLayout
llvm::BCRecordLayout< MODULE_NAME, llvm::BCBlob > ModuleNameLayout
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 > SelectorID
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
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...
uint32_t SelectorID
An ID number that refers to an ObjC selector in an AST file.
uint64_t IdentifierID
An ID number that refers to an identifier in an AST file.
unsigned ComputeHash(Selector Sel)
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.