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, uint8_t> ContextKinds;
57 llvm::DenseMap<unsigned, unsigned> ContextNames;
64 std::tuple<unsigned, unsigned, char>,
79 llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
91 llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
132 if (Identifier.empty())
136 return IdentifierIDs.try_emplace(Identifier, IdentifierIDs.size() + 1)
150 return SelectorIDs.try_emplace(
Selector, SelectorIDs.size()).first->second;
154 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
155 void writeControlBlock(llvm::BitstreamWriter &Stream);
156 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
157 void writeContextBlock(llvm::BitstreamWriter &Stream);
158 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
159 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
160 void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
161 void writeFieldBlock(llvm::BitstreamWriter &Stream);
162 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
163 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
164 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
165 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
166 void writeTagBlock(llvm::BitstreamWriter &Stream);
167 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
171 : ModuleName(
std::string(ModuleName)), SourceFile(SF) {}
180 llvm::BitstreamWriter Stream(Buffer);
184 Stream.Emit(Byte, 8);
187 writeBlockInfoBlock(Stream);
188 writeControlBlock(Stream);
189 writeIdentifierBlock(Stream);
190 writeContextBlock(Stream);
191 writeObjCPropertyBlock(Stream);
192 writeObjCMethodBlock(Stream);
193 writeCXXMethodBlock(Stream);
194 writeFieldBlock(Stream);
195 writeObjCSelectorBlock(Stream);
196 writeGlobalVariableBlock(Stream);
197 writeGlobalFunctionBlock(Stream);
198 writeEnumConstantBlock(Stream);
199 writeTagBlock(Stream);
200 writeTypedefBlock(Stream);
203 OS.write(Buffer.data(), Buffer.size());
209void emitBlockID(llvm::BitstreamWriter &Stream,
unsigned ID,
210 llvm::StringRef Name) {
211 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
218 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
220 const_cast<unsigned char *
>(
221 reinterpret_cast<const unsigned char *
>(Name.data())),
226void emitRecordID(llvm::BitstreamWriter &Stream,
unsigned ID,
227 llvm::StringRef Name) {
228 assert(ID < 256 &&
"can't fit record ID in next to name");
231 Buffer.resize(Name.size() + 1);
233 memcpy(Buffer.data() + 1, Name.data(), Name.size());
235 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
239void APINotesWriter::Implementation::writeBlockInfoBlock(
240 llvm::BitstreamWriter &Stream) {
241 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
243#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
244#define BLOCK_RECORD(NameSpace, Block) \
245 emitRecordID(Stream, NameSpace::Block, #Block)
246 BLOCK(CONTROL_BLOCK);
250 BLOCK(IDENTIFIER_BLOCK);
253 BLOCK(OBJC_CONTEXT_BLOCK);
256 BLOCK(OBJC_PROPERTY_BLOCK);
259 BLOCK(OBJC_METHOD_BLOCK);
262 BLOCK(OBJC_SELECTOR_BLOCK);
265 BLOCK(GLOBAL_VARIABLE_BLOCK);
266 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
268 BLOCK(GLOBAL_FUNCTION_BLOCK);
269 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
274void APINotesWriter::Implementation::writeControlBlock(
275 llvm::BitstreamWriter &Stream) {
282 ModuleName.emit(Scratch, this->ModuleName);
286 SourceFile.emit(Scratch, this->SourceFile->
getSize(),
287 this->SourceFile->getModificationTime());
293class IdentifierTableInfo {
295 using key_type = StringRef;
296 using key_type_ref = key_type;
298 using data_type_ref =
const data_type &;
300 using offset_type = unsigned;
302 hash_value_type
ComputeHash(key_type_ref Key) {
return llvm::djbHash(Key); }
304 std::pair<unsigned, unsigned>
305 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
309 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
310 writer.write<uint16_t>(KeyLength);
311 writer.write<uint16_t>(DataLength);
312 return {KeyLength, DataLength};
315 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
OS << Key; }
317 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
318 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
324void APINotesWriter::Implementation::writeIdentifierBlock(
325 llvm::BitstreamWriter &Stream) {
328 if (IdentifierIDs.empty())
331 llvm::SmallString<4096> HashTableBlob;
334 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo>
Generator;
335 for (
auto &II : IdentifierIDs)
338 llvm::raw_svector_ostream BlobStream(HashTableBlob);
340 llvm::support::endian::write<uint32_t>(BlobStream, 0,
341 llvm::endianness::little);
346 IdentifierData.emit(Scratch, Offset, HashTableBlob);
351class ContextIDTableInfo {
353 using key_type = ContextTableKey;
354 using key_type_ref = key_type;
355 using data_type = unsigned;
356 using data_type_ref =
const data_type &;
357 using hash_value_type =
size_t;
358 using offset_type = unsigned;
361 return static_cast<size_t>(Key.hashValue());
364 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
369 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
370 writer.write<uint16_t>(KeyLength);
371 writer.write<uint16_t>(DataLength);
372 return {KeyLength, DataLength};
375 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
376 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
377 writer.write<
uint32_t>(Key.parentContextID);
378 writer.write<uint8_t>(Key.contextKind);
379 writer.write<
uint32_t>(Key.contextID);
382 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
383 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
390template <
typename T>
struct MakeDependent {
typedef T Type; };
394unsigned getVersionTupleSize(
const VersionTuple &VT) {
395 unsigned size =
sizeof(uint8_t) +
sizeof(uint32_t);
398 if (VT.getSubminor())
407unsigned getVersionedInfoSize(
408 const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI,
409 llvm::function_ref<
unsigned(
const typename MakeDependent<T>::Type &)>
411 unsigned result =
sizeof(uint16_t);
412 for (
const auto &E : VI) {
413 result += getVersionTupleSize(E.first);
414 result += getInfoSize(E.second);
420void emitVersionTuple(raw_ostream &OS,
const VersionTuple &VT) {
421 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
427 else if (VT.getSubminor())
429 else if (VT.getMinor())
433 writer.write<uint8_t>(descriptor);
436 writer.write<
uint32_t>(VT.getMajor());
437 if (
auto minor = VT.getMinor())
439 if (
auto subminor = VT.getSubminor())
441 if (
auto build = VT.getBuild())
447void emitVersionedInfo(
448 raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI,
449 llvm::function_ref<
void(raw_ostream &,
450 const typename MakeDependent<T>::Type &)>
452 std::sort(VI.begin(), VI.end(),
453 [](
const std::pair<VersionTuple, T> &LHS,
454 const std::pair<VersionTuple, T> &RHS) ->
bool {
455 assert((&LHS == &RHS || LHS.first != RHS.first) &&
456 "two entries for the same version");
457 return LHS.first < RHS.first;
460 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
461 writer.write<uint16_t>(VI.size());
462 for (
const auto &E : VI) {
463 emitVersionTuple(OS, E.first);
464 emitInfo(OS, E.second);
469template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
470class VersionedTableInfo {
471 Derived &asDerived() {
return *
static_cast<Derived *
>(
this); }
473 const Derived &asDerived()
const {
474 return *
static_cast<const Derived *
>(
this);
478 using key_type = KeyType;
479 using key_type_ref = key_type;
481 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
482 using data_type_ref = data_type &;
483 using hash_value_type =
size_t;
484 using offset_type = unsigned;
486 std::pair<unsigned, unsigned>
487 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) {
488 uint32_t KeyLength = asDerived().getKeyLength(Key);
490 getVersionedInfoSize(Data, [
this](
const UnversionedDataType &UI) {
491 return asDerived().getUnversionedInfoSize(UI);
494 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
495 writer.write<uint16_t>(KeyLength);
496 writer.write<uint16_t>(DataLength);
497 return {KeyLength, DataLength};
500 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
502 OS, Data, [
this](llvm::raw_ostream &OS,
const UnversionedDataType &UI) {
503 asDerived().emitUnversionedInfo(OS, UI);
509void emitCommonEntityInfo(raw_ostream &OS,
const CommonEntityInfo &CEI) {
510 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
513 if (
auto safety = CEI.getSwiftSafety()) {
514 payload =
static_cast<unsigned>(*safety);
519 if (
auto swiftPrivate = CEI.isSwiftPrivate()) {
525 payload |= CEI.Unavailable;
527 payload |= CEI.UnavailableInSwift;
529 writer.write<uint8_t>(payload);
531 writer.write<uint16_t>(CEI.UnavailableMsg.size());
532 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
534 writer.write<uint16_t>(CEI.SwiftName.size());
535 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
540unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
541 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
546unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
547 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
548 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
549 (CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
550 getCommonEntityInfoSize(CTI);
554void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
555 emitCommonEntityInfo(OS, CTI);
557 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
558 if (
auto swiftBridge = CTI.getSwiftBridge()) {
559 writer.write<uint16_t>(swiftBridge->size() + 1);
560 OS.write(swiftBridge->c_str(), swiftBridge->size());
562 writer.write<uint16_t>(0);
564 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
565 writer.write<uint16_t>(nsErrorDomain->size() + 1);
566 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
568 writer.write<uint16_t>(0);
570 if (
auto conformance = CTI.getSwiftConformance()) {
571 writer.write<uint16_t>(conformance->size() + 1);
572 OS.write(conformance->c_str(), conformance->size());
574 writer.write<uint16_t>(0);
579class ContextInfoTableInfo
580 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
582 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
584 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
585 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
593 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
594 return getCommonTypeInfoSize(OCI) + 1;
597 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
598 emitCommonTypeInfo(OS, OCI);
601 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
602 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
604 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
605 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
607 if (
auto nullable = OCI.getDefaultNullability())
608 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
609 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
616void APINotesWriter::Implementation::writeContextBlock(
617 llvm::BitstreamWriter &Stream) {
620 if (Contexts.empty())
624 llvm::SmallString<4096> HashTableBlob;
627 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
628 for (
auto &OC : Contexts)
629 Generator.insert(OC.first, OC.second.first);
631 llvm::raw_svector_ostream BlobStream(HashTableBlob);
633 llvm::support::endian::write<uint32_t>(BlobStream, 0,
634 llvm::endianness::little);
639 ContextID.emit(Scratch, Offset, HashTableBlob);
643 llvm::SmallString<4096> HashTableBlob;
646 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
647 for (
auto &OC : Contexts)
648 Generator.insert(OC.second.first, OC.second.second);
650 llvm::raw_svector_ostream BlobStream(HashTableBlob);
652 llvm::support::endian::write<uint32_t>(BlobStream, 0,
653 llvm::endianness::little);
658 ContextInfo.emit(Scratch, Offset, HashTableBlob);
665unsigned getVariableInfoSize(
const VariableInfo &VI) {
666 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
668unsigned getParamInfoSize(
const ParamInfo &PI);
671void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
672 emitCommonEntityInfo(OS, VI);
674 uint8_t
bytes[2] = {0, 0};
675 if (
auto nullable = VI.getNullability()) {
677 bytes[1] =
static_cast<uint8_t
>(*nullable);
682 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
684 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
685 writer.write<uint16_t>(VI.getType().size());
686 OS.write(VI.getType().data(), VI.getType().size());
690class ObjCPropertyTableInfo
691 :
public VersionedTableInfo<ObjCPropertyTableInfo,
692 std::tuple<unsigned, unsigned, char>,
695 unsigned getKeyLength(key_type_ref) {
696 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
699 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
700 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
701 writer.write<
uint32_t>(std::get<0>(Key));
702 writer.write<
uint32_t>(std::get<1>(Key));
703 writer.write<uint8_t>(std::get<2>(Key));
710 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
711 return getVariableInfoSize(OPI) + 1;
714 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
715 emitVariableInfo(OS, OPI);
718 if (
auto value = OPI.getSwiftImportAsAccessors()) {
720 flags |= value.value() << 1;
727void APINotesWriter::Implementation::writeObjCPropertyBlock(
728 llvm::BitstreamWriter &Stream) {
731 if (ObjCProperties.empty())
735 llvm::SmallString<4096> HashTableBlob;
738 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
739 for (
auto &OP : ObjCProperties)
742 llvm::raw_svector_ostream BlobStream(HashTableBlob);
744 llvm::support::endian::write<uint32_t>(BlobStream, 0,
745 llvm::endianness::little);
750 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
755unsigned getFunctionInfoSize(
const FunctionInfo &);
756void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
757void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI);
760class ObjCMethodTableInfo
761 :
public VersionedTableInfo<ObjCMethodTableInfo,
762 std::tuple<unsigned, unsigned, char>,
765 unsigned getKeyLength(key_type_ref) {
766 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
769 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
770 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
771 writer.write<
uint32_t>(std::get<0>(Key));
772 writer.write<
uint32_t>(std::get<1>(Key));
773 writer.write<uint8_t>(std::get<2>(Key));
780 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
781 auto size = getFunctionInfoSize(OMI) + 1;
783 size += getParamInfoSize(*OMI.Self);
787 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
789 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
790 flags = (flags << 1) | OMI.DesignatedInit;
791 flags = (flags << 1) | OMI.RequiredInit;
792 flags = (flags << 1) | static_cast<bool>(OMI.Self);
793 writer.write<uint8_t>(flags);
795 emitFunctionInfo(OS, OMI);
798 emitParamInfo(OS, *OMI.Self);
803class CXXMethodTableInfo
804 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
807 unsigned getKeyLength(key_type_ref) {
808 return sizeof(
uint32_t) +
sizeof(uint32_t);
811 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
812 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
813 writer.write<
uint32_t>(Key.parentContextID);
818 return static_cast<size_t>(key.hashValue());
821 unsigned getUnversionedInfoSize(
const CXXMethodInfo &MI) {
822 auto size = getFunctionInfoSize(MI) + 1;
824 size += getParamInfoSize(*MI.This);
828 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &MI) {
830 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
831 flags = (flags << 1) | static_cast<bool>(MI.This);
832 writer.write<uint8_t>(flags);
834 emitFunctionInfo(OS, MI);
836 emitParamInfo(OS, *MI.This);
841void APINotesWriter::Implementation::writeObjCMethodBlock(
842 llvm::BitstreamWriter &Stream) {
845 if (ObjCMethods.empty())
849 llvm::SmallString<4096> HashTableBlob;
852 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
853 for (
auto &OM : ObjCMethods)
856 llvm::raw_svector_ostream BlobStream(HashTableBlob);
858 llvm::support::endian::write<uint32_t>(BlobStream, 0,
859 llvm::endianness::little);
864 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
868void APINotesWriter::Implementation::writeCXXMethodBlock(
869 llvm::BitstreamWriter &Stream) {
872 if (CXXMethods.empty())
876 llvm::SmallString<4096> HashTableBlob;
879 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
880 for (
auto &MD : CXXMethods)
883 llvm::raw_svector_ostream BlobStream(HashTableBlob);
885 llvm::support::endian::write<uint32_t>(BlobStream, 0,
886 llvm::endianness::little);
891 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
898 :
public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
900 unsigned getKeyLength(key_type_ref) {
901 return sizeof(
uint32_t) +
sizeof(uint32_t);
904 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
905 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
906 writer.write<
uint32_t>(Key.parentContextID);
911 return static_cast<size_t>(key.hashValue());
914 unsigned getUnversionedInfoSize(
const FieldInfo &FI) {
915 return getVariableInfoSize(FI);
918 void emitUnversionedInfo(raw_ostream &OS,
const FieldInfo &FI) {
919 emitVariableInfo(OS, FI);
924void APINotesWriter::Implementation::writeFieldBlock(
925 llvm::BitstreamWriter &Stream) {
932 llvm::SmallString<4096> HashTableBlob;
935 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo>
Generator;
936 for (
auto &FD : Fields)
939 llvm::raw_svector_ostream BlobStream(HashTableBlob);
941 llvm::support::endian::write<uint32_t>(BlobStream, 0,
942 llvm::endianness::little);
947 FieldData.emit(Scratch, Offset, HashTableBlob);
953class ObjCSelectorTableInfo {
955 using key_type = StoredObjCSelector;
956 using key_type_ref =
const key_type &;
958 using data_type_ref = data_type;
959 using hash_value_type = unsigned;
960 using offset_type = unsigned;
963 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
966 std::pair<unsigned, unsigned>
967 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
969 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
972 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
973 writer.write<uint16_t>(KeyLength);
974 writer.write<uint16_t>(DataLength);
975 return {KeyLength, DataLength};
978 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
979 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
980 writer.write<uint16_t>(Key.NumArgs);
981 for (
auto Identifier : Key.Identifiers)
985 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data,
unsigned) {
986 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
992void APINotesWriter::Implementation::writeObjCSelectorBlock(
993 llvm::BitstreamWriter &Stream) {
996 if (SelectorIDs.empty())
1000 llvm::SmallString<4096> HashTableBlob;
1003 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
1004 for (
auto &S : SelectorIDs)
1007 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1009 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1010 llvm::endianness::little);
1015 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
1021class GlobalVariableTableInfo
1022 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
1023 GlobalVariableInfo> {
1025 unsigned getKeyLength(key_type_ref) {
1026 return sizeof(
uint32_t) +
sizeof(uint32_t);
1029 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1030 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1031 writer.write<
uint32_t>(Key.parentContextID);
1032 writer.write<
uint32_t>(Key.nameID);
1036 return static_cast<size_t>(Key.hashValue());
1039 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
1040 return getVariableInfoSize(GVI);
1043 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
1044 emitVariableInfo(OS, GVI);
1049void APINotesWriter::Implementation::writeGlobalVariableBlock(
1050 llvm::BitstreamWriter &Stream) {
1053 if (GlobalVariables.empty())
1057 llvm::SmallString<4096> HashTableBlob;
1060 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
1061 for (
auto &GV : GlobalVariables)
1064 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1066 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1067 llvm::endianness::little);
1072 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1077unsigned getParamInfoSize(
const ParamInfo &PI) {
1078 return getVariableInfoSize(PI) + 1;
1081void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
1082 emitVariableInfo(OS, PI);
1085 if (
auto noescape = PI.isNoEscape()) {
1091 if (
auto lifetimebound = PI.isLifetimebound()) {
1097 if (
auto RCC = PI.getRetainCountConvention())
1098 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1100 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1101 writer.write<uint8_t>(flags);
1106unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1107 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1108 size +=
sizeof(uint16_t);
1109 for (
const auto &P : FI.Params)
1110 size += getParamInfoSize(P);
1111 size +=
sizeof(uint16_t) + FI.ResultType.size();
1112 size +=
sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
1117void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1118 emitCommonEntityInfo(OS, FI);
1121 flags |= FI.NullabilityAudited;
1123 if (
auto RCC = FI.getRetainCountConvention())
1124 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1126 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1128 writer.write<uint8_t>(flags);
1129 writer.write<uint8_t>(FI.NumAdjustedNullable);
1130 writer.write<
uint64_t>(FI.NullabilityPayload);
1132 writer.write<uint16_t>(FI.Params.size());
1133 for (
const auto &PI : FI.Params)
1134 emitParamInfo(OS, PI);
1136 writer.write<uint16_t>(FI.ResultType.size());
1137 writer.write(ArrayRef<char>{FI.ResultType});
1138 writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1139 writer.write(ArrayRef<char>{FI.SwiftReturnOwnership});
1143class GlobalFunctionTableInfo
1144 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1145 GlobalFunctionInfo> {
1147 unsigned getKeyLength(key_type_ref) {
1148 return sizeof(
uint32_t) +
sizeof(uint32_t);
1151 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1152 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1153 writer.write<
uint32_t>(Key.parentContextID);
1154 writer.write<
uint32_t>(Key.nameID);
1158 return static_cast<size_t>(Key.hashValue());
1161 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1162 return getFunctionInfoSize(GFI);
1165 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1166 emitFunctionInfo(OS, GFI);
1171void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1172 llvm::BitstreamWriter &Stream) {
1175 if (GlobalFunctions.empty())
1179 llvm::SmallString<4096> HashTableBlob;
1182 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1183 for (
auto &F : GlobalFunctions)
1186 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1188 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1189 llvm::endianness::little);
1194 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1200class EnumConstantTableInfo
1201 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1204 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
1206 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1207 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1215 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1216 return getCommonEntityInfoSize(ECI);
1219 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1220 emitCommonEntityInfo(OS, ECI);
1225void APINotesWriter::Implementation::writeEnumConstantBlock(
1226 llvm::BitstreamWriter &Stream) {
1229 if (EnumConstants.empty())
1233 llvm::SmallString<4096> HashTableBlob;
1236 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1237 for (
auto &EC : EnumConstants)
1240 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1242 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1243 llvm::endianness::little);
1248 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1253template <
typename Derived,
typename UnversionedDataType>
1254class CommonTypeTableInfo
1255 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1256 UnversionedDataType> {
1258 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1259 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1261 unsigned getKeyLength(key_type_ref) {
1262 return sizeof(
uint32_t) +
sizeof(IdentifierID);
1265 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1266 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1267 writer.write<
uint32_t>(Key.parentContextID);
1272 return static_cast<size_t>(Key.hashValue());
1275 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1276 return getCommonTypeInfoSize(UDT);
1279 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1280 emitCommonTypeInfo(OS, UDT);
1285class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1287 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1289 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1290 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1291 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1292 2 + (TI.SwiftDestroyOp ? TI.SwiftDestroyOp->size() : 0) +
1293 2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1294 3 + getCommonTypeInfoSize(TI);
1298 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1299 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1302 if (
auto extensibility = TI.EnumExtensibility) {
1303 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1304 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1308 if (
auto value = TI.isFlagEnum())
1309 Flags |= (value.value() << 1 | 1 << 0);
1311 writer.write<uint8_t>(Flags);
1313 if (
auto Copyable = TI.isSwiftCopyable())
1316 writer.write<uint8_t>(0);
1318 if (
auto Escapable = TI.isSwiftEscapable())
1321 writer.write<uint8_t>(0);
1323 if (
auto ImportAs = TI.SwiftImportAs) {
1324 writer.write<uint16_t>(ImportAs->size() + 1);
1325 OS.write(ImportAs->c_str(), ImportAs->size());
1327 writer.write<uint16_t>(0);
1329 if (
auto RetainOp = TI.SwiftRetainOp) {
1330 writer.write<uint16_t>(RetainOp->size() + 1);
1331 OS.write(RetainOp->c_str(), RetainOp->size());
1333 writer.write<uint16_t>(0);
1335 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1336 writer.write<uint16_t>(ReleaseOp->size() + 1);
1337 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1339 writer.write<uint16_t>(0);
1341 if (
auto DefaultOwnership = TI.SwiftDefaultOwnership) {
1342 writer.write<uint16_t>(DefaultOwnership->size() + 1);
1343 OS.write(DefaultOwnership->c_str(), DefaultOwnership->size());
1345 writer.write<uint16_t>(0);
1347 if (
auto DestroyOp = TI.SwiftDestroyOp) {
1348 writer.write<uint16_t>(DestroyOp->size() + 1);
1349 OS.write(DestroyOp->c_str(), DestroyOp->size());
1351 writer.write<uint16_t>(0);
1354 emitCommonTypeInfo(OS, TI);
1359void APINotesWriter::Implementation::writeTagBlock(
1360 llvm::BitstreamWriter &Stream) {
1367 llvm::SmallString<4096> HashTableBlob;
1370 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1371 for (
auto &T : Tags)
1374 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1376 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1377 llvm::endianness::little);
1382 TagData.emit(Scratch, Offset, HashTableBlob);
1388class TypedefTableInfo
1389 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1391 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1392 return 1 + getCommonTypeInfoSize(TI);
1395 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1396 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1399 if (
auto swiftWrapper = TI.SwiftWrapper)
1400 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1402 writer.write<uint8_t>(Flags);
1404 emitCommonTypeInfo(OS, TI);
1409void APINotesWriter::Implementation::writeTypedefBlock(
1410 llvm::BitstreamWriter &Stream) {
1413 if (Typedefs.empty())
1417 llvm::SmallString<4096> HashTableBlob;
1420 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1421 for (
auto &T : Typedefs)
1424 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1426 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1427 llvm::endianness::little);
1432 TypedefData.emit(Scratch, Offset, HashTableBlob);
1450 llvm::VersionTuple SwiftVersion) {
1453 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1454 ContextTableKey Key(RawParentCtxID,
static_cast<uint8_t
>(Kind), NameID);
1459 Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo;
1461 .insert(std::make_pair(
1462 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1467 Implementation->ContextKinds[NextID] =
static_cast<uint8_t
>(Kind);
1471 auto &VersionedVec = Known->second.second;
1473 for (
auto &Versioned : VersionedVec) {
1474 if (Versioned.first == SwiftVersion) {
1475 Versioned.second |= Info;
1482 VersionedVec.push_back({SwiftVersion, Info});
1488 bool IsInstanceProperty,
1490 VersionTuple SwiftVersion) {
1493 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1494 .push_back({SwiftVersion, Info});
1498 bool IsInstanceMethod,
1500 VersionTuple SwiftVersion) {
1502 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1504 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1517 for (
auto &Versioned : VersionedVec) {
1518 if (Versioned.first == SwiftVersion) {
1519 Versioned.second.setHasDesignatedInits(
true);
1526 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1527 VersionedVec.back().second.setHasDesignatedInits(
true);
1534 VersionTuple SwiftVersion) {
1542 VersionTuple SwiftVersion) {
1549 llvm::StringRef Name,
1551 VersionTuple SwiftVersion) {
1554 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1558 llvm::StringRef Name,
1560 VersionTuple SwiftVersion) {
1563 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1568 VersionTuple SwiftVersion) {
1570 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1574 const TagInfo &Info, VersionTuple SwiftVersion) {
1582 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.
hash_code hash_value(const clang::dependencies::ModuleID &ID)
A stored Objective-C or C++ context, represented by the ID of its parent context, the kind of this co...
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
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.