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 if (Known != IdentifierIDs.end())
134 return Known->second;
137 Known = IdentifierIDs.insert({
Identifier, IdentifierIDs.size() + 1}).first;
138 return Known->second;
151 auto Known = SelectorIDs.find(
Selector);
152 if (Known != SelectorIDs.end())
153 return Known->second;
156 Known = SelectorIDs.insert({
Selector, SelectorIDs.size()}).first;
157 return Known->second;
161 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
162 void writeControlBlock(llvm::BitstreamWriter &Stream);
163 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
164 void writeContextBlock(llvm::BitstreamWriter &Stream);
165 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
166 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
167 void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
168 void writeFieldBlock(llvm::BitstreamWriter &Stream);
169 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
170 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
171 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
172 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
173 void writeTagBlock(llvm::BitstreamWriter &Stream);
174 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
178 : ModuleName(
std::string(ModuleName)), SourceFile(SF) {}
187 llvm::BitstreamWriter Stream(Buffer);
191 Stream.Emit(Byte, 8);
194 writeBlockInfoBlock(Stream);
195 writeControlBlock(Stream);
196 writeIdentifierBlock(Stream);
197 writeContextBlock(Stream);
198 writeObjCPropertyBlock(Stream);
199 writeObjCMethodBlock(Stream);
200 writeCXXMethodBlock(Stream);
201 writeFieldBlock(Stream);
202 writeObjCSelectorBlock(Stream);
203 writeGlobalVariableBlock(Stream);
204 writeGlobalFunctionBlock(Stream);
205 writeEnumConstantBlock(Stream);
206 writeTagBlock(Stream);
207 writeTypedefBlock(Stream);
210 OS.write(Buffer.data(), Buffer.size());
217 llvm::StringRef Name) {
218 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
225 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
227 const_cast<unsigned char *
>(
228 reinterpret_cast<const unsigned char *
>(Name.data())),
234 llvm::StringRef Name) {
235 assert(
ID < 256 &&
"can't fit record ID in next to name");
238 Buffer.resize(Name.size() + 1);
240 memcpy(Buffer.data() + 1, Name.data(), Name.size());
242 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
246void APINotesWriter::Implementation::writeBlockInfoBlock(
247 llvm::BitstreamWriter &Stream) {
248 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
250#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
251#define BLOCK_RECORD(NameSpace, Block) \
252 emitRecordID(Stream, NameSpace::Block, #Block)
253 BLOCK(CONTROL_BLOCK);
257 BLOCK(IDENTIFIER_BLOCK);
260 BLOCK(OBJC_CONTEXT_BLOCK);
263 BLOCK(OBJC_PROPERTY_BLOCK);
266 BLOCK(OBJC_METHOD_BLOCK);
269 BLOCK(OBJC_SELECTOR_BLOCK);
272 BLOCK(GLOBAL_VARIABLE_BLOCK);
273 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
275 BLOCK(GLOBAL_FUNCTION_BLOCK);
276 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
281void APINotesWriter::Implementation::writeControlBlock(
282 llvm::BitstreamWriter &Stream) {
289 ModuleName.emit(Scratch, this->ModuleName);
293 SourceFile.emit(Scratch, this->SourceFile->
getSize(),
294 this->SourceFile->getModificationTime());
300class IdentifierTableInfo {
302 using key_type = StringRef;
303 using key_type_ref = key_type;
305 using data_type_ref =
const data_type &;
309 hash_value_type
ComputeHash(key_type_ref Key) {
return llvm::djbHash(Key); }
311 std::pair<unsigned, unsigned>
312 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
316 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
317 writer.write<uint16_t>(KeyLength);
318 writer.write<uint16_t>(DataLength);
319 return {KeyLength, DataLength};
322 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) { OS << Key; }
324 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
325 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
331void APINotesWriter::Implementation::writeIdentifierBlock(
332 llvm::BitstreamWriter &Stream) {
335 if (IdentifierIDs.empty())
341 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo>
Generator;
342 for (
auto &II : IdentifierIDs)
345 llvm::raw_svector_ostream BlobStream(HashTableBlob);
347 llvm::support::endian::write<uint32_t>(BlobStream, 0,
348 llvm::endianness::little);
353 IdentifierData.emit(Scratch, Offset, HashTableBlob);
358class ContextIDTableInfo {
360 using key_type = ContextTableKey;
361 using key_type_ref = key_type;
363 using data_type_ref =
const data_type &;
364 using hash_value_type =
size_t;
368 return static_cast<size_t>(Key.hashValue());
371 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
376 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
377 writer.write<uint16_t>(KeyLength);
378 writer.write<uint16_t>(DataLength);
379 return {KeyLength, DataLength};
382 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
383 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
384 writer.write<
uint32_t>(Key.parentContextID);
385 writer.write<uint8_t>(Key.contextKind);
386 writer.write<
uint32_t>(Key.contextID);
389 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
390 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
397template <
typename T>
struct MakeDependent {
typedef T Type; };
401unsigned getVersionTupleSize(
const VersionTuple &VT) {
402 unsigned size =
sizeof(uint8_t) +
sizeof(uint32_t);
404 size +=
sizeof(uint32_t);
405 if (VT.getSubminor())
406 size +=
sizeof(uint32_t);
408 size +=
sizeof(uint32_t);
414unsigned getVersionedInfoSize(
416 llvm::function_ref<
unsigned(
const typename MakeDependent<T>::Type &)>
418 unsigned result =
sizeof(uint16_t);
419 for (
const auto &
E : VI) {
420 result += getVersionTupleSize(
E.first);
421 result += getInfoSize(
E.second);
427void emitVersionTuple(raw_ostream &OS,
const VersionTuple &VT) {
428 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
434 else if (VT.getSubminor())
436 else if (VT.getMinor())
440 writer.write<uint8_t>(descriptor);
443 writer.write<
uint32_t>(VT.getMajor());
444 if (
auto minor = VT.getMinor())
445 writer.write<uint32_t>(*minor);
446 if (
auto subminor = VT.getSubminor())
447 writer.write<uint32_t>(*subminor);
448 if (
auto build = VT.getBuild())
449 writer.write<uint32_t>(*build);
454void emitVersionedInfo(
456 llvm::function_ref<
void(raw_ostream &,
457 const typename MakeDependent<T>::Type &)>
459 std::sort(VI.begin(), VI.end(),
460 [](
const std::pair<VersionTuple, T> &LHS,
461 const std::pair<VersionTuple, T> &RHS) ->
bool {
462 assert((&LHS == &RHS || LHS.first != RHS.first) &&
463 "two entries for the same version");
464 return LHS.first < RHS.first;
467 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
468 writer.write<uint16_t>(VI.size());
469 for (
const auto &
E : VI) {
470 emitVersionTuple(OS,
E.first);
471 emitInfo(OS,
E.second);
476template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
477class VersionedTableInfo {
478 Derived &asDerived() {
return *
static_cast<Derived *
>(
this); }
480 const Derived &asDerived()
const {
481 return *
static_cast<const Derived *
>(
this);
485 using key_type = KeyType;
486 using key_type_ref = key_type;
489 using data_type_ref = data_type &;
490 using hash_value_type =
size_t;
493 std::pair<unsigned, unsigned>
494 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref
Data) {
495 uint32_t KeyLength = asDerived().getKeyLength(Key);
497 getVersionedInfoSize(
Data, [
this](
const UnversionedDataType &UI) {
498 return asDerived().getUnversionedInfoSize(UI);
501 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
502 writer.write<uint16_t>(KeyLength);
503 writer.write<uint16_t>(DataLength);
504 return {KeyLength, DataLength};
507 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
509 OS,
Data, [
this](llvm::raw_ostream &OS,
const UnversionedDataType &UI) {
510 asDerived().emitUnversionedInfo(OS, UI);
516void emitCommonEntityInfo(raw_ostream &OS,
const CommonEntityInfo &CEI) {
517 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
520 if (
auto swiftPrivate = CEI.isSwiftPrivate()) {
526 payload |= CEI.Unavailable;
528 payload |= CEI.UnavailableInSwift;
530 writer.write<uint8_t>(payload);
532 writer.write<uint16_t>(CEI.UnavailableMsg.size());
533 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
535 writer.write<uint16_t>(CEI.SwiftName.size());
536 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
541unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
542 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
547unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
548 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
549 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->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);
573class ContextInfoTableInfo
574 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
576 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
578 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
579 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
587 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
588 return getCommonTypeInfoSize(OCI) + 1;
591 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
592 emitCommonTypeInfo(OS, OCI);
595 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
596 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
598 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
599 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
601 if (
auto nullable = OCI.getDefaultNullability())
602 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
603 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
610void APINotesWriter::Implementation::writeContextBlock(
611 llvm::BitstreamWriter &Stream) {
614 if (Contexts.empty())
621 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
622 for (
auto &OC : Contexts)
623 Generator.insert(OC.first, OC.second.first);
625 llvm::raw_svector_ostream BlobStream(HashTableBlob);
627 llvm::support::endian::write<uint32_t>(BlobStream, 0,
628 llvm::endianness::little);
633 ContextID.emit(Scratch, Offset, HashTableBlob);
640 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
641 for (
auto &OC : Contexts)
642 Generator.insert(OC.second.first, OC.second.second);
644 llvm::raw_svector_ostream BlobStream(HashTableBlob);
646 llvm::support::endian::write<uint32_t>(BlobStream, 0,
647 llvm::endianness::little);
652 ContextInfo.emit(Scratch, Offset, HashTableBlob);
659unsigned getVariableInfoSize(
const VariableInfo &VI) {
660 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
664void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
665 emitCommonEntityInfo(OS, VI);
667 uint8_t
bytes[2] = {0, 0};
668 if (
auto nullable = VI.getNullability()) {
670 bytes[1] =
static_cast<uint8_t
>(*nullable);
675 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
677 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
678 writer.write<uint16_t>(VI.getType().size());
679 OS.write(VI.getType().data(), VI.getType().size());
683class ObjCPropertyTableInfo
684 :
public VersionedTableInfo<ObjCPropertyTableInfo,
685 std::tuple<unsigned, unsigned, char>,
688 unsigned getKeyLength(key_type_ref) {
689 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
692 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
693 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
694 writer.write<
uint32_t>(std::get<0>(Key));
695 writer.write<
uint32_t>(std::get<1>(Key));
696 writer.write<uint8_t>(std::get<2>(Key));
703 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
704 return getVariableInfoSize(OPI) + 1;
707 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
708 emitVariableInfo(OS, OPI);
711 if (
auto value = OPI.getSwiftImportAsAccessors()) {
713 flags |= value.value() << 1;
720void APINotesWriter::Implementation::writeObjCPropertyBlock(
721 llvm::BitstreamWriter &Stream) {
724 if (ObjCProperties.empty())
731 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
732 for (
auto &OP : ObjCProperties)
735 llvm::raw_svector_ostream BlobStream(HashTableBlob);
737 llvm::support::endian::write<uint32_t>(BlobStream, 0,
738 llvm::endianness::little);
743 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
748unsigned getFunctionInfoSize(
const FunctionInfo &);
749void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
752class ObjCMethodTableInfo
753 :
public VersionedTableInfo<ObjCMethodTableInfo,
754 std::tuple<unsigned, unsigned, char>,
757 unsigned getKeyLength(key_type_ref) {
758 return sizeof(
uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
761 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
762 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
763 writer.write<
uint32_t>(std::get<0>(Key));
764 writer.write<
uint32_t>(std::get<1>(Key));
765 writer.write<uint8_t>(std::get<2>(Key));
772 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
773 return getFunctionInfoSize(OMI) + 1;
776 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
778 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
779 flags = (flags << 1) | OMI.DesignatedInit;
780 flags = (flags << 1) | OMI.RequiredInit;
781 writer.write<uint8_t>(flags);
783 emitFunctionInfo(OS, OMI);
788class CXXMethodTableInfo
789 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
792 unsigned getKeyLength(key_type_ref) {
793 return sizeof(
uint32_t) +
sizeof(uint32_t);
796 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
797 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
798 writer.write<
uint32_t>(Key.parentContextID);
803 return static_cast<size_t>(key.hashValue());
806 unsigned getUnversionedInfoSize(
const CXXMethodInfo &OMI) {
807 return getFunctionInfoSize(OMI);
810 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &OMI) {
811 emitFunctionInfo(OS, OMI);
816void APINotesWriter::Implementation::writeObjCMethodBlock(
817 llvm::BitstreamWriter &Stream) {
820 if (ObjCMethods.empty())
827 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
828 for (
auto &OM : ObjCMethods)
831 llvm::raw_svector_ostream BlobStream(HashTableBlob);
833 llvm::support::endian::write<uint32_t>(BlobStream, 0,
834 llvm::endianness::little);
839 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
843void APINotesWriter::Implementation::writeCXXMethodBlock(
844 llvm::BitstreamWriter &Stream) {
847 if (CXXMethods.empty())
854 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
855 for (
auto &MD : CXXMethods)
858 llvm::raw_svector_ostream BlobStream(HashTableBlob);
860 llvm::support::endian::write<uint32_t>(BlobStream, 0,
861 llvm::endianness::little);
866 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
873 :
public VersionedTableInfo<FieldTableInfo, SingleDeclTableKey, FieldInfo> {
875 unsigned getKeyLength(key_type_ref) {
876 return sizeof(
uint32_t) +
sizeof(uint32_t);
879 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
880 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
881 writer.write<
uint32_t>(Key.parentContextID);
886 return static_cast<size_t>(key.hashValue());
889 unsigned getUnversionedInfoSize(
const FieldInfo &FI) {
890 return getVariableInfoSize(FI);
893 void emitUnversionedInfo(raw_ostream &OS,
const FieldInfo &FI) {
894 emitVariableInfo(OS, FI);
899void APINotesWriter::Implementation::writeFieldBlock(
900 llvm::BitstreamWriter &Stream) {
910 llvm::OnDiskChainedHashTableGenerator<FieldTableInfo>
Generator;
911 for (
auto &FD : Fields)
914 llvm::raw_svector_ostream BlobStream(HashTableBlob);
916 llvm::support::endian::write<uint32_t>(BlobStream, 0,
917 llvm::endianness::little);
922 FieldData.emit(Scratch, Offset, HashTableBlob);
928class ObjCSelectorTableInfo {
930 using key_type = StoredObjCSelector;
931 using key_type_ref =
const key_type &;
933 using data_type_ref = data_type;
938 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
941 std::pair<unsigned, unsigned>
942 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
944 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
947 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
948 writer.write<uint16_t>(KeyLength);
949 writer.write<uint16_t>(DataLength);
950 return {KeyLength, DataLength};
953 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
954 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
955 writer.write<uint16_t>(Key.NumArgs);
960 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
961 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
967void APINotesWriter::Implementation::writeObjCSelectorBlock(
968 llvm::BitstreamWriter &Stream) {
971 if (SelectorIDs.empty())
978 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
979 for (
auto &S : SelectorIDs)
982 llvm::raw_svector_ostream BlobStream(HashTableBlob);
984 llvm::support::endian::write<uint32_t>(BlobStream, 0,
985 llvm::endianness::little);
990 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
996class GlobalVariableTableInfo
997 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
998 GlobalVariableInfo> {
1000 unsigned getKeyLength(key_type_ref) {
1001 return sizeof(
uint32_t) +
sizeof(uint32_t);
1004 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1005 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1006 writer.write<
uint32_t>(Key.parentContextID);
1007 writer.write<
uint32_t>(Key.nameID);
1011 return static_cast<size_t>(Key.hashValue());
1014 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
1015 return getVariableInfoSize(GVI);
1018 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
1019 emitVariableInfo(OS, GVI);
1024void APINotesWriter::Implementation::writeGlobalVariableBlock(
1025 llvm::BitstreamWriter &Stream) {
1028 if (GlobalVariables.empty())
1035 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
1036 for (
auto &GV : GlobalVariables)
1039 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1041 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1042 llvm::endianness::little);
1047 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
1052unsigned getParamInfoSize(
const ParamInfo &PI) {
1053 return getVariableInfoSize(PI) + 1;
1056void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
1057 emitVariableInfo(OS, PI);
1060 if (
auto noescape = PI.isNoEscape()) {
1066 if (
auto RCC = PI.getRetainCountConvention())
1067 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1069 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1070 writer.write<uint8_t>(flags);
1075unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1076 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1077 size +=
sizeof(uint16_t);
1078 for (
const auto &
P : FI.Params)
1079 size += getParamInfoSize(
P);
1080 size +=
sizeof(uint16_t) + FI.ResultType.size();
1085void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1086 emitCommonEntityInfo(OS, FI);
1089 flags |= FI.NullabilityAudited;
1091 if (
auto RCC = FI.getRetainCountConvention())
1092 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1094 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1096 writer.write<uint8_t>(flags);
1097 writer.write<uint8_t>(FI.NumAdjustedNullable);
1098 writer.write<
uint64_t>(FI.NullabilityPayload);
1100 writer.write<uint16_t>(FI.Params.size());
1101 for (
const auto &PI : FI.Params)
1102 emitParamInfo(OS, PI);
1104 writer.write<uint16_t>(FI.ResultType.size());
1105 writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
1109class GlobalFunctionTableInfo
1110 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1111 GlobalFunctionInfo> {
1113 unsigned getKeyLength(key_type_ref) {
1114 return sizeof(
uint32_t) +
sizeof(uint32_t);
1117 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1118 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1119 writer.write<
uint32_t>(Key.parentContextID);
1120 writer.write<
uint32_t>(Key.nameID);
1124 return static_cast<size_t>(Key.hashValue());
1127 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1128 return getFunctionInfoSize(GFI);
1131 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1132 emitFunctionInfo(OS, GFI);
1137void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1138 llvm::BitstreamWriter &Stream) {
1141 if (GlobalFunctions.empty())
1148 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1149 for (
auto &F : GlobalFunctions)
1152 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1154 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1155 llvm::endianness::little);
1160 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1166class EnumConstantTableInfo
1167 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1170 unsigned getKeyLength(key_type_ref) {
return sizeof(
uint32_t); }
1172 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1173 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1181 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1182 return getCommonEntityInfoSize(ECI);
1185 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1186 emitCommonEntityInfo(OS, ECI);
1191void APINotesWriter::Implementation::writeEnumConstantBlock(
1192 llvm::BitstreamWriter &Stream) {
1195 if (EnumConstants.empty())
1202 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1203 for (
auto &EC : EnumConstants)
1206 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1208 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1209 llvm::endianness::little);
1214 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1219template <
typename Derived,
typename UnversionedDataType>
1220class CommonTypeTableInfo
1221 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1222 UnversionedDataType> {
1224 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1225 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1227 unsigned getKeyLength(key_type_ref) {
1228 return sizeof(
uint32_t) +
sizeof(IdentifierID);
1231 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1232 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1233 writer.write<
uint32_t>(Key.parentContextID);
1238 return static_cast<size_t>(Key.hashValue());
1241 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1242 return getCommonTypeInfoSize(UDT);
1245 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1246 emitCommonTypeInfo(OS, UDT);
1251class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1253 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1254 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1255 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1256 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1257 2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
1258 2 + getCommonTypeInfoSize(TI);
1261 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1262 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1265 if (
auto extensibility = TI.EnumExtensibility) {
1266 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1267 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1271 if (
auto value = TI.isFlagEnum())
1272 Flags |= (value.value() << 1 | 1 << 0);
1274 writer.write<uint8_t>(Flags);
1276 if (
auto Copyable = TI.isSwiftCopyable())
1277 writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
1279 writer.write<uint8_t>(0);
1281 if (
auto ImportAs = TI.SwiftImportAs) {
1282 writer.write<uint16_t>(ImportAs->size() + 1);
1283 OS.write(ImportAs->c_str(), ImportAs->size());
1285 writer.write<uint16_t>(0);
1287 if (
auto RetainOp = TI.SwiftRetainOp) {
1288 writer.write<uint16_t>(RetainOp->size() + 1);
1289 OS.write(RetainOp->c_str(), RetainOp->size());
1291 writer.write<uint16_t>(0);
1293 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1294 writer.write<uint16_t>(ReleaseOp->size() + 1);
1295 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1297 writer.write<uint16_t>(0);
1299 if (
auto Conformance = TI.SwiftConformance) {
1300 writer.write<uint16_t>(Conformance->size() + 1);
1301 OS.write(Conformance->c_str(), Conformance->size());
1303 writer.write<uint16_t>(0);
1306 emitCommonTypeInfo(OS, TI);
1311void APINotesWriter::Implementation::writeTagBlock(
1312 llvm::BitstreamWriter &Stream) {
1322 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1323 for (
auto &
T : Tags)
1326 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1328 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1329 llvm::endianness::little);
1334 TagData.emit(Scratch, Offset, HashTableBlob);
1340class TypedefTableInfo
1341 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1343 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1344 return 1 + getCommonTypeInfoSize(TI);
1347 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1348 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1351 if (
auto swiftWrapper = TI.SwiftWrapper)
1352 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1354 writer.write<uint8_t>(Flags);
1356 emitCommonTypeInfo(OS, TI);
1361void APINotesWriter::Implementation::writeTypedefBlock(
1362 llvm::BitstreamWriter &Stream) {
1365 if (Typedefs.empty())
1372 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1373 for (
auto &
T : Typedefs)
1376 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1378 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1379 llvm::endianness::little);
1384 TypedefData.emit(Scratch, Offset, HashTableBlob);
1402 llvm::VersionTuple SwiftVersion) {
1405 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1413 .insert(std::make_pair(
1414 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1422 auto &VersionedVec = Known->second.second;
1424 for (
auto &Versioned : VersionedVec) {
1425 if (Versioned.first == SwiftVersion) {
1426 Versioned.second |= Info;
1433 VersionedVec.push_back({SwiftVersion, Info});
1439 bool IsInstanceProperty,
1441 VersionTuple SwiftVersion) {
1444 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1445 .push_back({SwiftVersion, Info});
1449 bool IsInstanceMethod,
1451 VersionTuple SwiftVersion) {
1453 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1455 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1468 for (
auto &Versioned : VersionedVec) {
1469 if (Versioned.first == SwiftVersion) {
1470 Versioned.second.setHasDesignatedInits(
true);
1477 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1478 VersionedVec.back().second.setHasDesignatedInits(
true);
1485 VersionTuple SwiftVersion) {
1493 VersionTuple SwiftVersion) {
1500 llvm::StringRef Name,
1502 VersionTuple SwiftVersion) {
1505 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1509 llvm::StringRef Name,
1511 VersionTuple SwiftVersion) {
1514 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1519 VersionTuple SwiftVersion) {
1521 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1525 const TagInfo &Info, VersionTuple SwiftVersion) {
1533 VersionTuple SwiftVersion) {
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
enum clang::sema::@1655::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.