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) +
540 getCommonEntityInfoSize(CTI);
544void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
545 emitCommonEntityInfo(OS, CTI);
547 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
548 if (
auto swiftBridge = CTI.getSwiftBridge()) {
549 writer.write<uint16_t>(swiftBridge->size() + 1);
550 OS.write(swiftBridge->c_str(), swiftBridge->size());
552 writer.write<uint16_t>(0);
554 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
555 writer.write<uint16_t>(nsErrorDomain->size() + 1);
556 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
558 writer.write<uint16_t>(0);
563class ContextInfoTableInfo
564 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
566 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
568 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
569 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
577 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
578 return getCommonTypeInfoSize(OCI) + 1;
581 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
582 emitCommonTypeInfo(OS, OCI);
585 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
586 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
588 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
589 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
591 if (
auto nullable = OCI.getDefaultNullability())
592 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
593 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
600void APINotesWriter::Implementation::writeContextBlock(
601 llvm::BitstreamWriter &Stream) {
604 if (Contexts.empty())
611 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
612 for (
auto &OC : Contexts)
613 Generator.insert(OC.first, OC.second.first);
615 llvm::raw_svector_ostream BlobStream(HashTableBlob);
617 llvm::support::endian::write<uint32_t>(BlobStream, 0,
618 llvm::endianness::little);
623 ContextID.emit(Scratch, Offset, HashTableBlob);
630 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
631 for (
auto &OC : Contexts)
632 Generator.insert(OC.second.first, OC.second.second);
634 llvm::raw_svector_ostream BlobStream(HashTableBlob);
636 llvm::support::endian::write<uint32_t>(BlobStream, 0,
637 llvm::endianness::little);
642 ContextInfo.emit(Scratch, Offset, HashTableBlob);
649unsigned getVariableInfoSize(
const VariableInfo &VI) {
650 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
652unsigned getParamInfoSize(
const ParamInfo &PI);
655void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
656 emitCommonEntityInfo(OS, VI);
658 uint8_t
bytes[2] = {0, 0};
659 if (
auto nullable = VI.getNullability()) {
661 bytes[1] =
static_cast<uint8_t
>(*nullable);
666 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
668 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
669 writer.write<uint16_t>(VI.getType().size());
670 OS.write(VI.getType().data(), VI.getType().size());
674class ObjCPropertyTableInfo
675 :
public VersionedTableInfo<ObjCPropertyTableInfo,
676 std::tuple<unsigned, unsigned, char>,
679 unsigned getKeyLength(key_type_ref) {
680 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
683 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
684 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
685 writer.write<
uint32_t>(std::get<0>(Key));
686 writer.write<
uint32_t>(std::get<1>(Key));
687 writer.write<uint8_t>(std::get<2>(Key));
694 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
695 return getVariableInfoSize(OPI) + 1;
698 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
699 emitVariableInfo(OS, OPI);
702 if (
auto value = OPI.getSwiftImportAsAccessors()) {
704 flags |= value.value() << 1;
711void APINotesWriter::Implementation::writeObjCPropertyBlock(
712 llvm::BitstreamWriter &Stream) {
715 if (ObjCProperties.empty())
722 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
723 for (
auto &OP : ObjCProperties)
726 llvm::raw_svector_ostream BlobStream(HashTableBlob);
728 llvm::support::endian::write<uint32_t>(BlobStream, 0,
729 llvm::endianness::little);
734 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
739unsigned getFunctionInfoSize(
const FunctionInfo &);
740void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
741void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI);
744class ObjCMethodTableInfo
745 :
public VersionedTableInfo<ObjCMethodTableInfo,
746 std::tuple<unsigned, unsigned, char>,
749 unsigned getKeyLength(key_type_ref) {
750 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
753 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
754 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
755 writer.write<
uint32_t>(std::get<0>(Key));
756 writer.write<
uint32_t>(std::get<1>(Key));
757 writer.write<uint8_t>(std::get<2>(Key));
764 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
765 auto size = getFunctionInfoSize(OMI) + 1;
767 size += getParamInfoSize(*OMI.Self);
771 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
773 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
774 flags = (flags << 1) | OMI.DesignatedInit;
775 flags = (flags << 1) | OMI.RequiredInit;
776 flags = (flags << 1) | static_cast<bool>(OMI.Self);
777 writer.write<uint8_t>(flags);
779 emitFunctionInfo(OS, OMI);
782 emitParamInfo(OS, *OMI.Self);
787class CXXMethodTableInfo
788 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
791 unsigned getKeyLength(key_type_ref) {
792 return sizeof(
uint32_t) +
sizeof(uint32_t);
795 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
796 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
797 writer.write<
uint32_t>(Key.parentContextID);
802 return static_cast<size_t>(key.hashValue());
805 unsigned getUnversionedInfoSize(
const CXXMethodInfo &MI) {
806 auto size = getFunctionInfoSize(MI) + 1;
808 size += getParamInfoSize(*MI.This);
812 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &MI) {
814 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
815 flags = (flags << 1) | static_cast<bool>(MI.This);
816 writer.write<uint8_t>(flags);
818 emitFunctionInfo(OS, MI);
820 emitParamInfo(OS, *MI.This);
825void APINotesWriter::Implementation::writeObjCMethodBlock(
826 llvm::BitstreamWriter &Stream) {
829 if (ObjCMethods.empty())
836 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
837 for (
auto &OM : ObjCMethods)
840 llvm::raw_svector_ostream BlobStream(HashTableBlob);
842 llvm::support::endian::write<uint32_t>(BlobStream, 0,
843 llvm::endianness::little);
848 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
852void APINotesWriter::Implementation::writeCXXMethodBlock(
853 llvm::BitstreamWriter &Stream) {
856 if (CXXMethods.empty())
863 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
864 for (
auto &MD : CXXMethods)
867 llvm::raw_svector_ostream BlobStream(HashTableBlob);
869 llvm::support::endian::write<uint32_t>(BlobStream, 0,
870 llvm::endianness::little);
875 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
882 :
public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
884 unsigned getKeyLength(key_type_ref) {
885 return sizeof(
uint32_t) +
sizeof(uint32_t);
888 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
889 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
890 writer.write<
uint32_t>(Key.parentContextID);
895 return static_cast<size_t>(key.hashValue());
898 unsigned getUnversionedInfoSize(
const FieldInfo &FI) {
899 return getVariableInfoSize(FI);
902 void emitUnversionedInfo(raw_ostream &OS,
const FieldInfo &FI) {
903 emitVariableInfo(OS, FI);
908void APINotesWriter::Implementation::writeFieldBlock(
909 llvm::BitstreamWriter &Stream) {
919 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo>
Generator;
920 for (
auto &FD : Fields)
923 llvm::raw_svector_ostream BlobStream(HashTableBlob);
925 llvm::support::endian::write<uint32_t>(BlobStream, 0,
926 llvm::endianness::little);
931 FieldData.emit(Scratch, Offset, HashTableBlob);
937class ObjCSelectorTableInfo {
939 using key_type = StoredObjCSelector;
940 using key_type_ref =
const key_type &;
942 using data_type_ref = data_type;
947 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
950 std::pair<unsigned, unsigned>
951 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
953 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
956 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
957 writer.write<uint16_t>(KeyLength);
958 writer.write<uint16_t>(DataLength);
959 return {KeyLength, DataLength};
962 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
963 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
964 writer.write<uint16_t>(Key.NumArgs);
969 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
970 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
976void APINotesWriter::Implementation::writeObjCSelectorBlock(
977 llvm::BitstreamWriter &Stream) {
980 if (SelectorIDs.empty())
987 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
988 for (
auto &S : SelectorIDs)
991 llvm::raw_svector_ostream BlobStream(HashTableBlob);
993 llvm::support::endian::write<uint32_t>(BlobStream, 0,
994 llvm::endianness::little);
999 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
1005class GlobalVariableTableInfo
1006 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
1007 GlobalVariableInfo> {
1009 unsigned getKeyLength(key_type_ref) {
1010 return sizeof(
uint32_t) +
sizeof(uint32_t);
1013 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1014 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1015 writer.write<
uint32_t>(Key.parentContextID);
1016 writer.write<
uint32_t>(Key.nameID);
1020 return static_cast<size_t>(Key.hashValue());
1023 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
1024 return getVariableInfoSize(GVI);
1027 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
1028 emitVariableInfo(OS, GVI);
1033void APINotesWriter::Implementation::writeGlobalVariableBlock(
1034 llvm::BitstreamWriter &Stream) {
1037 if (GlobalVariables.empty())
1044 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
1045 for (
auto &GV : GlobalVariables)
1048 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1050 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1051 llvm::endianness::little);
1056 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1061unsigned getParamInfoSize(
const ParamInfo &PI) {
1062 return getVariableInfoSize(PI) + 1;
1065void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
1066 emitVariableInfo(OS, PI);
1069 if (
auto noescape = PI.isNoEscape()) {
1075 if (
auto lifetimebound = PI.isLifetimebound()) {
1081 if (
auto RCC = PI.getRetainCountConvention())
1082 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1084 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1085 writer.write<uint8_t>(flags);
1090unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1091 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1092 size +=
sizeof(uint16_t);
1093 for (
const auto &
P : FI.Params)
1094 size += getParamInfoSize(
P);
1095 size +=
sizeof(uint16_t) + FI.ResultType.size();
1096 size +=
sizeof(uint16_t) + FI.SwiftReturnOwnership.size();
1101void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1102 emitCommonEntityInfo(OS, FI);
1105 flags |= FI.NullabilityAudited;
1107 if (
auto RCC = FI.getRetainCountConvention())
1108 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1110 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1112 writer.write<uint8_t>(flags);
1113 writer.write<uint8_t>(FI.NumAdjustedNullable);
1114 writer.write<
uint64_t>(FI.NullabilityPayload);
1116 writer.write<uint16_t>(FI.Params.size());
1117 for (
const auto &PI : FI.Params)
1118 emitParamInfo(OS, PI);
1120 writer.write<uint16_t>(FI.ResultType.size());
1121 writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
1122 writer.write<uint16_t>(FI.SwiftReturnOwnership.size());
1123 writer.write(ArrayRef<char>{FI.SwiftReturnOwnership.data(),
1124 FI.SwiftReturnOwnership.size()});
1128class GlobalFunctionTableInfo
1129 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1130 GlobalFunctionInfo> {
1132 unsigned getKeyLength(key_type_ref) {
1133 return sizeof(
uint32_t) +
sizeof(uint32_t);
1136 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1137 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1138 writer.write<
uint32_t>(Key.parentContextID);
1139 writer.write<
uint32_t>(Key.nameID);
1143 return static_cast<size_t>(Key.hashValue());
1146 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1147 return getFunctionInfoSize(GFI);
1150 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1151 emitFunctionInfo(OS, GFI);
1156void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1157 llvm::BitstreamWriter &Stream) {
1160 if (GlobalFunctions.empty())
1167 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1168 for (
auto &F : GlobalFunctions)
1171 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1173 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1174 llvm::endianness::little);
1179 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1185class EnumConstantTableInfo
1186 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1189 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
1191 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1192 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1200 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1201 return getCommonEntityInfoSize(ECI);
1204 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1205 emitCommonEntityInfo(OS, ECI);
1210void APINotesWriter::Implementation::writeEnumConstantBlock(
1211 llvm::BitstreamWriter &Stream) {
1214 if (EnumConstants.empty())
1221 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1222 for (
auto &EC : EnumConstants)
1225 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1227 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1228 llvm::endianness::little);
1233 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1238template <
typename Derived,
typename UnversionedDataType>
1239class CommonTypeTableInfo
1240 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1241 UnversionedDataType> {
1243 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1244 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1246 unsigned getKeyLength(key_type_ref) {
1247 return sizeof(
uint32_t) +
sizeof(IdentifierID);
1250 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1251 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1252 writer.write<
uint32_t>(Key.parentContextID);
1257 return static_cast<size_t>(Key.hashValue());
1260 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1261 return getCommonTypeInfoSize(UDT);
1264 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1265 emitCommonTypeInfo(OS, UDT);
1270class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1272 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1274 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1275 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1276 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1277 2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
1278 3 + getCommonTypeInfoSize(TI);
1282 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1283 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1286 if (
auto extensibility = TI.EnumExtensibility) {
1287 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1288 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1292 if (
auto value = TI.isFlagEnum())
1293 Flags |= (value.value() << 1 | 1 << 0);
1295 writer.write<uint8_t>(Flags);
1297 if (
auto Copyable = TI.isSwiftCopyable())
1298 writer.write<uint8_t>(*Copyable ? kSwiftConforms : kSwiftDoesNotConform);
1300 writer.write<uint8_t>(0);
1302 if (
auto Escapable = TI.isSwiftEscapable())
1303 writer.write<uint8_t>(*Escapable ? kSwiftConforms : kSwiftDoesNotConform);
1305 writer.write<uint8_t>(0);
1307 if (
auto ImportAs = TI.SwiftImportAs) {
1308 writer.write<uint16_t>(ImportAs->size() + 1);
1309 OS.write(ImportAs->c_str(), ImportAs->size());
1311 writer.write<uint16_t>(0);
1313 if (
auto RetainOp = TI.SwiftRetainOp) {
1314 writer.write<uint16_t>(RetainOp->size() + 1);
1315 OS.write(RetainOp->c_str(), RetainOp->size());
1317 writer.write<uint16_t>(0);
1319 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1320 writer.write<uint16_t>(ReleaseOp->size() + 1);
1321 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1323 writer.write<uint16_t>(0);
1325 if (
auto Conformance = TI.SwiftConformance) {
1326 writer.write<uint16_t>(Conformance->size() + 1);
1327 OS.write(Conformance->c_str(), Conformance->size());
1329 writer.write<uint16_t>(0);
1332 emitCommonTypeInfo(OS, TI);
1337void APINotesWriter::Implementation::writeTagBlock(
1338 llvm::BitstreamWriter &Stream) {
1348 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1349 for (
auto &
T : Tags)
1352 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1354 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1355 llvm::endianness::little);
1360 TagData.emit(Scratch, Offset, HashTableBlob);
1366class TypedefTableInfo
1367 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1369 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1370 return 1 + getCommonTypeInfoSize(TI);
1373 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1374 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1377 if (
auto swiftWrapper = TI.SwiftWrapper)
1378 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1380 writer.write<uint8_t>(Flags);
1382 emitCommonTypeInfo(OS, TI);
1387void APINotesWriter::Implementation::writeTypedefBlock(
1388 llvm::BitstreamWriter &Stream) {
1391 if (Typedefs.empty())
1398 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1399 for (
auto &
T : Typedefs)
1402 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1404 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1405 llvm::endianness::little);
1410 TypedefData.emit(Scratch, Offset, HashTableBlob);
1428 llvm::VersionTuple SwiftVersion) {
1431 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1439 .insert(std::make_pair(
1440 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1448 auto &VersionedVec = Known->second.second;
1450 for (
auto &Versioned : VersionedVec) {
1451 if (Versioned.first == SwiftVersion) {
1452 Versioned.second |= Info;
1459 VersionedVec.push_back({SwiftVersion, Info});
1465 bool IsInstanceProperty,
1467 VersionTuple SwiftVersion) {
1470 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1471 .push_back({SwiftVersion, Info});
1475 bool IsInstanceMethod,
1477 VersionTuple SwiftVersion) {
1479 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1481 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1494 for (
auto &Versioned : VersionedVec) {
1495 if (Versioned.first == SwiftVersion) {
1496 Versioned.second.setHasDesignatedInits(
true);
1503 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1504 VersionedVec.back().second.setHasDesignatedInits(
true);
1511 VersionTuple SwiftVersion) {
1519 VersionTuple SwiftVersion) {
1526 llvm::StringRef Name,
1528 VersionTuple SwiftVersion) {
1531 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1535 llvm::StringRef Name,
1537 VersionTuple SwiftVersion) {
1540 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1545 VersionTuple SwiftVersion) {
1547 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1551 const TagInfo &Info, VersionTuple SwiftVersion) {
1559 VersionTuple SwiftVersion) {
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
enum clang::sema::@1718::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.