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<ObjCContextInfo>>>
51 llvm::DenseMap<uint32_t, uint32_t> ParentContexts;
54 llvm::DenseMap<unsigned, unsigned> ObjCContextNames;
61 std::tuple<unsigned, unsigned, char>,
69 llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
74 llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
119 if (Known != IdentifierIDs.end())
120 return Known->second;
123 Known = IdentifierIDs.insert({
Identifier, IdentifierIDs.size() + 1}).first;
124 return Known->second;
137 auto Known = SelectorIDs.find(
Selector);
138 if (Known != SelectorIDs.end())
139 return Known->second;
142 Known = SelectorIDs.insert({
Selector, SelectorIDs.size()}).first;
143 return Known->second;
147 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
148 void writeControlBlock(llvm::BitstreamWriter &Stream);
149 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
150 void writeObjCContextBlock(llvm::BitstreamWriter &Stream);
151 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
152 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
153 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
154 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
155 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
156 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
157 void writeTagBlock(llvm::BitstreamWriter &Stream);
158 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
162 : ModuleName(
std::string(ModuleName)), SourceFile(SF) {}
171 llvm::BitstreamWriter Stream(Buffer);
175 Stream.Emit(Byte, 8);
178 writeBlockInfoBlock(Stream);
179 writeControlBlock(Stream);
180 writeIdentifierBlock(Stream);
181 writeObjCContextBlock(Stream);
182 writeObjCPropertyBlock(Stream);
183 writeObjCMethodBlock(Stream);
184 writeObjCSelectorBlock(Stream);
185 writeGlobalVariableBlock(Stream);
186 writeGlobalFunctionBlock(Stream);
187 writeEnumConstantBlock(Stream);
188 writeTagBlock(Stream);
189 writeTypedefBlock(Stream);
192 OS.write(Buffer.data(), Buffer.size());
199 llvm::StringRef Name) {
200 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
207 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
209 const_cast<unsigned char *
>(
210 reinterpret_cast<const unsigned char *
>(Name.data())),
216 llvm::StringRef Name) {
217 assert(
ID < 256 &&
"can't fit record ID in next to name");
220 Buffer.resize(Name.size() + 1);
222 memcpy(Buffer.data() + 1, Name.data(), Name.size());
224 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
228void APINotesWriter::Implementation::writeBlockInfoBlock(
229 llvm::BitstreamWriter &Stream) {
230 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
232#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
233#define BLOCK_RECORD(NameSpace, Block) \
234 emitRecordID(Stream, NameSpace::Block, #Block)
235 BLOCK(CONTROL_BLOCK);
239 BLOCK(IDENTIFIER_BLOCK);
242 BLOCK(OBJC_CONTEXT_BLOCK);
245 BLOCK(OBJC_PROPERTY_BLOCK);
248 BLOCK(OBJC_METHOD_BLOCK);
251 BLOCK(OBJC_SELECTOR_BLOCK);
254 BLOCK(GLOBAL_VARIABLE_BLOCK);
255 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
257 BLOCK(GLOBAL_FUNCTION_BLOCK);
258 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
263void APINotesWriter::Implementation::writeControlBlock(
264 llvm::BitstreamWriter &Stream) {
271 ModuleName.emit(Scratch, this->ModuleName);
275 SourceFile.emit(Scratch, this->SourceFile->
getSize(),
276 this->SourceFile->getModificationTime());
282class IdentifierTableInfo {
284 using key_type = StringRef;
285 using key_type_ref = key_type;
287 using data_type_ref =
const data_type &;
288 using hash_value_type = uint32_t;
291 hash_value_type
ComputeHash(key_type_ref Key) {
return llvm::djbHash(Key); }
293 std::pair<unsigned, unsigned>
294 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
295 uint32_t KeyLength = Key.size();
296 uint32_t DataLength =
sizeof(uint32_t);
298 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
299 writer.write<uint16_t>(KeyLength);
300 writer.write<uint16_t>(DataLength);
301 return {KeyLength, DataLength};
304 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) { OS << Key; }
306 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
307 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
308 writer.write<uint32_t>(
Data);
313void APINotesWriter::Implementation::writeIdentifierBlock(
314 llvm::BitstreamWriter &Stream) {
317 if (IdentifierIDs.empty())
323 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo>
Generator;
324 for (
auto &II : IdentifierIDs)
327 llvm::raw_svector_ostream BlobStream(HashTableBlob);
329 llvm::support::endian::write<uint32_t>(BlobStream, 0,
330 llvm::endianness::little);
335 IdentifierData.emit(Scratch, Offset, HashTableBlob);
340class ObjCContextIDTableInfo {
342 using key_type = ContextTableKey;
343 using key_type_ref = key_type;
345 using data_type_ref =
const data_type &;
346 using hash_value_type =
size_t;
350 return static_cast<size_t>(Key.hashValue());
353 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
355 uint32_t KeyLength =
sizeof(uint32_t) +
sizeof(uint8_t) +
sizeof(uint32_t);
356 uint32_t DataLength =
sizeof(uint32_t);
358 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
359 writer.write<uint16_t>(KeyLength);
360 writer.write<uint16_t>(DataLength);
361 return {KeyLength, DataLength};
364 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
365 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
366 writer.write<uint32_t>(Key.parentContextID);
367 writer.write<uint8_t>(Key.contextKind);
368 writer.write<uint32_t>(Key.contextID);
371 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
372 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
373 writer.write<uint32_t>(
Data);
379template <
typename T>
struct MakeDependent {
typedef T Type; };
383unsigned getVersionTupleSize(
const VersionTuple &VT) {
384 unsigned size =
sizeof(uint8_t) +
sizeof(uint32_t);
386 size +=
sizeof(uint32_t);
387 if (VT.getSubminor())
388 size +=
sizeof(uint32_t);
390 size +=
sizeof(uint32_t);
396unsigned getVersionedInfoSize(
398 llvm::function_ref<
unsigned(
const typename MakeDependent<T>::Type &)>
400 unsigned result =
sizeof(uint16_t);
401 for (
const auto &E : VI) {
402 result += getVersionTupleSize(E.first);
403 result += getInfoSize(E.second);
409void emitVersionTuple(raw_ostream &OS,
const VersionTuple &VT) {
410 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
416 else if (VT.getSubminor())
418 else if (VT.getMinor())
422 writer.write<uint8_t>(descriptor);
425 writer.write<uint32_t>(VT.getMajor());
426 if (
auto minor = VT.getMinor())
427 writer.write<uint32_t>(*minor);
428 if (
auto subminor = VT.getSubminor())
429 writer.write<uint32_t>(*subminor);
430 if (
auto build = VT.getBuild())
431 writer.write<uint32_t>(*build);
436void emitVersionedInfo(
438 llvm::function_ref<
void(raw_ostream &,
439 const typename MakeDependent<T>::Type &)>
441 std::sort(VI.begin(), VI.end(),
442 [](
const std::pair<VersionTuple, T> &LHS,
443 const std::pair<VersionTuple, T> &RHS) ->
bool {
444 assert((&LHS == &RHS || LHS.first != RHS.first) &&
445 "two entries for the same version");
446 return LHS.first < RHS.first;
449 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
450 writer.write<uint16_t>(VI.size());
451 for (
const auto &E : VI) {
452 emitVersionTuple(OS, E.first);
453 emitInfo(OS, E.second);
458template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
459class VersionedTableInfo {
460 Derived &asDerived() {
return *
static_cast<Derived *
>(
this); }
462 const Derived &asDerived()
const {
463 return *
static_cast<const Derived *
>(
this);
467 using key_type = KeyType;
468 using key_type_ref = key_type;
471 using data_type_ref = data_type &;
472 using hash_value_type =
size_t;
475 std::pair<unsigned, unsigned>
476 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref
Data) {
477 uint32_t KeyLength = asDerived().getKeyLength(Key);
478 uint32_t DataLength =
479 getVersionedInfoSize(
Data, [
this](
const UnversionedDataType &UI) {
480 return asDerived().getUnversionedInfoSize(UI);
483 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
484 writer.write<uint16_t>(KeyLength);
485 writer.write<uint16_t>(DataLength);
486 return {KeyLength, DataLength};
489 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
491 OS,
Data, [
this](llvm::raw_ostream &OS,
const UnversionedDataType &UI) {
492 asDerived().emitUnversionedInfo(OS, UI);
498void emitCommonEntityInfo(raw_ostream &OS,
const CommonEntityInfo &CEI) {
499 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
502 if (
auto swiftPrivate = CEI.isSwiftPrivate()) {
508 payload |= CEI.Unavailable;
510 payload |= CEI.UnavailableInSwift;
512 writer.write<uint8_t>(payload);
514 writer.write<uint16_t>(CEI.UnavailableMsg.size());
515 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
517 writer.write<uint16_t>(CEI.SwiftName.size());
518 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
523unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
524 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
529unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
530 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
531 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
532 getCommonEntityInfoSize(CTI);
536void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
537 emitCommonEntityInfo(OS, CTI);
539 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
540 if (
auto swiftBridge = CTI.getSwiftBridge()) {
541 writer.write<uint16_t>(swiftBridge->size() + 1);
542 OS.write(swiftBridge->c_str(), swiftBridge->size());
544 writer.write<uint16_t>(0);
546 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
547 writer.write<uint16_t>(nsErrorDomain->size() + 1);
548 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
550 writer.write<uint16_t>(0);
555class ObjCContextInfoTableInfo
556 :
public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
559 unsigned getKeyLength(key_type_ref) {
return sizeof(uint32_t); }
561 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
562 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
563 writer.write<uint32_t>(Key);
570 unsigned getUnversionedInfoSize(
const ObjCContextInfo &OCI) {
571 return getCommonTypeInfoSize(OCI) + 1;
574 void emitUnversionedInfo(raw_ostream &OS,
const ObjCContextInfo &OCI) {
575 emitCommonTypeInfo(OS, OCI);
578 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
579 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
581 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
582 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
584 if (
auto nullable = OCI.getDefaultNullability())
585 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
586 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
593void APINotesWriter::Implementation::writeObjCContextBlock(
594 llvm::BitstreamWriter &Stream) {
597 if (ObjCContexts.empty())
604 llvm::OnDiskChainedHashTableGenerator<ObjCContextIDTableInfo>
Generator;
605 for (
auto &OC : ObjCContexts)
606 Generator.insert(OC.first, OC.second.first);
608 llvm::raw_svector_ostream BlobStream(HashTableBlob);
610 llvm::support::endian::write<uint32_t>(BlobStream, 0,
611 llvm::endianness::little);
616 ObjCContextID.emit(Scratch, Offset, HashTableBlob);
623 llvm::OnDiskChainedHashTableGenerator<ObjCContextInfoTableInfo>
Generator;
624 for (
auto &OC : ObjCContexts)
625 Generator.insert(OC.second.first, OC.second.second);
627 llvm::raw_svector_ostream BlobStream(HashTableBlob);
629 llvm::support::endian::write<uint32_t>(BlobStream, 0,
630 llvm::endianness::little);
635 ObjCContextInfo.emit(Scratch, Offset, HashTableBlob);
642unsigned getVariableInfoSize(
const VariableInfo &VI) {
643 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
647void emitVariableInfo(raw_ostream &OS,
const VariableInfo &VI) {
648 emitCommonEntityInfo(OS, VI);
650 uint8_t
bytes[2] = {0, 0};
651 if (
auto nullable = VI.getNullability()) {
653 bytes[1] =
static_cast<uint8_t
>(*nullable);
658 OS.write(
reinterpret_cast<const char *
>(
bytes), 2);
660 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
661 writer.write<uint16_t>(VI.getType().size());
662 OS.write(VI.getType().data(), VI.getType().size());
666class ObjCPropertyTableInfo
667 :
public VersionedTableInfo<ObjCPropertyTableInfo,
668 std::tuple<unsigned, unsigned, char>,
671 unsigned getKeyLength(key_type_ref) {
672 return sizeof(uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
675 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
676 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
677 writer.write<uint32_t>(std::get<0>(Key));
678 writer.write<uint32_t>(std::get<1>(Key));
679 writer.write<uint8_t>(std::get<2>(Key));
686 unsigned getUnversionedInfoSize(
const ObjCPropertyInfo &OPI) {
687 return getVariableInfoSize(OPI) + 1;
690 void emitUnversionedInfo(raw_ostream &OS,
const ObjCPropertyInfo &OPI) {
691 emitVariableInfo(OS, OPI);
694 if (
auto value = OPI.getSwiftImportAsAccessors()) {
696 flags |= value.value() << 1;
703void APINotesWriter::Implementation::writeObjCPropertyBlock(
704 llvm::BitstreamWriter &Stream) {
707 if (ObjCProperties.empty())
714 llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo>
Generator;
715 for (
auto &OP : ObjCProperties)
718 llvm::raw_svector_ostream BlobStream(HashTableBlob);
720 llvm::support::endian::write<uint32_t>(BlobStream, 0,
721 llvm::endianness::little);
726 ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
731unsigned getFunctionInfoSize(
const FunctionInfo &);
732void emitFunctionInfo(llvm::raw_ostream &,
const FunctionInfo &);
735class ObjCMethodTableInfo
736 :
public VersionedTableInfo<ObjCMethodTableInfo,
737 std::tuple<unsigned, unsigned, char>,
740 unsigned getKeyLength(key_type_ref) {
741 return sizeof(uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
744 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
745 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
746 writer.write<uint32_t>(std::get<0>(Key));
747 writer.write<uint32_t>(std::get<1>(Key));
748 writer.write<uint8_t>(std::get<2>(Key));
755 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
756 return getFunctionInfoSize(OMI) + 1;
759 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
761 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
762 flags = (flags << 1) | OMI.DesignatedInit;
763 flags = (flags << 1) | OMI.RequiredInit;
764 writer.write<uint8_t>(flags);
766 emitFunctionInfo(OS, OMI);
771void APINotesWriter::Implementation::writeObjCMethodBlock(
772 llvm::BitstreamWriter &Stream) {
775 if (ObjCMethods.empty())
782 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
783 for (
auto &OM : ObjCMethods)
786 llvm::raw_svector_ostream BlobStream(HashTableBlob);
788 llvm::support::endian::write<uint32_t>(BlobStream, 0,
789 llvm::endianness::little);
794 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
800class ObjCSelectorTableInfo {
802 using key_type = StoredObjCSelector;
803 using key_type_ref =
const key_type &;
805 using data_type_ref = data_type;
810 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
813 std::pair<unsigned, unsigned>
814 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
816 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
817 uint32_t DataLength =
sizeof(uint32_t);
819 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
820 writer.write<uint16_t>(KeyLength);
821 writer.write<uint16_t>(DataLength);
822 return {KeyLength, DataLength};
825 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
826 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
827 writer.write<uint16_t>(Key.NumArgs);
832 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
833 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
834 writer.write<uint32_t>(
Data);
839void APINotesWriter::Implementation::writeObjCSelectorBlock(
840 llvm::BitstreamWriter &Stream) {
843 if (SelectorIDs.empty())
850 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
851 for (
auto &S : SelectorIDs)
854 llvm::raw_svector_ostream BlobStream(HashTableBlob);
856 llvm::support::endian::write<uint32_t>(BlobStream, 0,
857 llvm::endianness::little);
862 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
868class GlobalVariableTableInfo
869 :
public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
870 GlobalVariableInfo> {
872 unsigned getKeyLength(key_type_ref) {
873 return sizeof(uint32_t) +
sizeof(uint8_t) +
sizeof(uint32_t);
876 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
877 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
878 writer.write<uint32_t>(Key.parentContextID);
879 writer.write<uint8_t>(Key.contextKind);
880 writer.write<uint32_t>(Key.contextID);
884 return static_cast<size_t>(Key.hashValue());
887 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
888 return getVariableInfoSize(GVI);
891 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
892 emitVariableInfo(OS, GVI);
897void APINotesWriter::Implementation::writeGlobalVariableBlock(
898 llvm::BitstreamWriter &Stream) {
901 if (GlobalVariables.empty())
908 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
909 for (
auto &GV : GlobalVariables)
912 llvm::raw_svector_ostream BlobStream(HashTableBlob);
914 llvm::support::endian::write<uint32_t>(BlobStream, 0,
915 llvm::endianness::little);
920 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
925unsigned getParamInfoSize(
const ParamInfo &PI) {
926 return getVariableInfoSize(PI) + 1;
929void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
930 emitVariableInfo(OS, PI);
933 if (
auto noescape = PI.isNoEscape()) {
939 if (
auto RCC = PI.getRetainCountConvention())
940 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
942 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
943 writer.write<uint8_t>(flags);
948unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
949 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
950 size +=
sizeof(uint16_t);
951 for (
const auto &
P : FI.Params)
952 size += getParamInfoSize(
P);
953 size +=
sizeof(uint16_t) + FI.ResultType.size();
958void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
959 emitCommonEntityInfo(OS, FI);
962 flags |= FI.NullabilityAudited;
964 if (
auto RCC = FI.getRetainCountConvention())
965 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
967 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
969 writer.write<uint8_t>(flags);
970 writer.write<uint8_t>(FI.NumAdjustedNullable);
971 writer.write<
uint64_t>(FI.NullabilityPayload);
973 writer.write<uint16_t>(FI.Params.size());
974 for (
const auto &PI : FI.Params)
975 emitParamInfo(OS, PI);
977 writer.write<uint16_t>(FI.ResultType.size());
978 writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
982class GlobalFunctionTableInfo
983 :
public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
984 GlobalFunctionInfo> {
986 unsigned getKeyLength(key_type_ref) {
987 return sizeof(uint32_t) +
sizeof(uint8_t) +
sizeof(uint32_t);
990 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
991 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
992 writer.write<uint32_t>(Key.parentContextID);
993 writer.write<uint8_t>(Key.contextKind);
994 writer.write<uint32_t>(Key.contextID);
998 return static_cast<size_t>(Key.hashValue());
1001 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1002 return getFunctionInfoSize(GFI);
1005 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1006 emitFunctionInfo(OS, GFI);
1011void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1012 llvm::BitstreamWriter &Stream) {
1015 if (GlobalFunctions.empty())
1022 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1023 for (
auto &F : GlobalFunctions)
1026 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1028 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1029 llvm::endianness::little);
1034 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1040class EnumConstantTableInfo
1041 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1044 unsigned getKeyLength(key_type_ref) {
return sizeof(uint32_t); }
1046 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1047 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1048 writer.write<uint32_t>(Key);
1055 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1056 return getCommonEntityInfoSize(ECI);
1059 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1060 emitCommonEntityInfo(OS, ECI);
1065void APINotesWriter::Implementation::writeEnumConstantBlock(
1066 llvm::BitstreamWriter &Stream) {
1069 if (EnumConstants.empty())
1076 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1077 for (
auto &EC : EnumConstants)
1080 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1082 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1083 llvm::endianness::little);
1088 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1093template <
typename Derived,
typename UnversionedDataType>
1094class CommonTypeTableInfo
1095 :
public VersionedTableInfo<Derived, ContextTableKey, UnversionedDataType> {
1097 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1098 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1100 unsigned getKeyLength(key_type_ref) {
1101 return sizeof(uint32_t) +
sizeof(uint8_t) +
sizeof(
IdentifierID);
1104 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1105 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1106 writer.write<uint32_t>(Key.parentContextID);
1107 writer.write<uint8_t>(Key.contextKind);
1112 return static_cast<size_t>(Key.hashValue());
1115 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1116 return getCommonTypeInfoSize(UDT);
1119 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1120 emitCommonTypeInfo(OS, UDT);
1125class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1127 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1128 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1129 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1130 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1131 2 + getCommonTypeInfoSize(TI);
1134 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1135 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1138 if (
auto extensibility = TI.EnumExtensibility) {
1139 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1140 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1144 if (
auto value = TI.isFlagEnum())
1145 Flags |= (value.value() << 1 | 1 << 0);
1147 writer.write<uint8_t>(Flags);
1149 if (
auto Copyable = TI.isSwiftCopyable())
1150 writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
1152 writer.write<uint8_t>(0);
1154 if (
auto ImportAs = TI.SwiftImportAs) {
1155 writer.write<uint16_t>(ImportAs->size() + 1);
1156 OS.write(ImportAs->c_str(), ImportAs->size());
1158 writer.write<uint16_t>(0);
1160 if (
auto RetainOp = TI.SwiftRetainOp) {
1161 writer.write<uint16_t>(RetainOp->size() + 1);
1162 OS.write(RetainOp->c_str(), RetainOp->size());
1164 writer.write<uint16_t>(0);
1166 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1167 writer.write<uint16_t>(ReleaseOp->size() + 1);
1168 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1170 writer.write<uint16_t>(0);
1173 emitCommonTypeInfo(OS, TI);
1178void APINotesWriter::Implementation::writeTagBlock(
1179 llvm::BitstreamWriter &Stream) {
1189 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1190 for (
auto &
T : Tags)
1193 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1195 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1196 llvm::endianness::little);
1201 TagData.emit(Scratch, Offset, HashTableBlob);
1207class TypedefTableInfo
1208 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1210 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1211 return 1 + getCommonTypeInfoSize(TI);
1214 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1215 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1218 if (
auto swiftWrapper = TI.SwiftWrapper)
1219 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1221 writer.write<uint8_t>(Flags);
1223 emitCommonTypeInfo(OS, TI);
1228void APINotesWriter::Implementation::writeTypedefBlock(
1229 llvm::BitstreamWriter &Stream) {
1232 if (Typedefs.empty())
1239 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1240 for (
auto &
T : Typedefs)
1243 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1245 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1246 llvm::endianness::little);
1251 TypedefData.emit(Scratch, Offset, HashTableBlob);
1269 VersionTuple SwiftVersion) {
1272 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1273 ContextTableKey Key(RawParentCtxID,
static_cast<uint8_t
>(Kind), NameID);
1280 .insert(std::make_pair(
1281 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1289 auto &VersionedVec = Known->second.second;
1291 for (
auto &Versioned : VersionedVec) {
1292 if (Versioned.first == SwiftVersion) {
1293 Versioned.second |= Info;
1300 VersionedVec.push_back({SwiftVersion, Info});
1306 bool IsInstanceProperty,
1308 VersionTuple SwiftVersion) {
1311 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1312 .push_back({SwiftVersion, Info});
1316 bool IsInstanceMethod,
1318 VersionTuple SwiftVersion) {
1320 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1322 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1333 auto &VersionedVec =
Implementation->ObjCContexts[CtxKey].second;
1335 for (
auto &Versioned : VersionedVec) {
1336 if (Versioned.first == SwiftVersion) {
1337 Versioned.second.setHasDesignatedInits(
true);
1345 VersionedVec.back().second.setHasDesignatedInits(
true);
1351 llvm::StringRef Name,
1353 VersionTuple SwiftVersion) {
1356 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1360 llvm::StringRef Name,
1362 VersionTuple SwiftVersion) {
1365 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1370 VersionTuple SwiftVersion) {
1372 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1376 const TagInfo &Info, VersionTuple SwiftVersion) {
1384 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)
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.
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 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)
ContextID addObjCContext(std::optional< ContextID > ParentCtxID, llvm::StringRef Name, ContextKind Kind, const ObjCContextInfo &Info, llvm::VersionTuple SwiftVersion)
Add information about a specific Objective-C class or protocol or a C++ namespace.
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.
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
Describes API notes data for an enumerator.
Describes API notes data for a global function.
Describes API notes data for a global variable.
Describes API notes data for an Objective-C class or protocol.
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< 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< ENUM_CONSTANT_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > EnumConstantDataLayout
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_CONTEXT_ID_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ObjCContextIDLayout
llvm::BCRecordLayout< OBJC_CONTEXT_INFO_DATA, llvm::BCVBR< 16 >, llvm::BCBlob > ObjCContextInfoLayout
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,...
@ OBJC_SELECTOR_BLOCK_ID
The Objective-C selector data block, which maps Objective-C selector names (# of pieces,...
@ 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.
uint32_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 selector.