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>,
69 llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
81 llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
126 if (Known != IdentifierIDs.end())
127 return Known->second;
130 Known = IdentifierIDs.insert({
Identifier, IdentifierIDs.size() + 1}).first;
131 return Known->second;
144 auto Known = SelectorIDs.find(
Selector);
145 if (Known != SelectorIDs.end())
146 return Known->second;
149 Known = SelectorIDs.insert({
Selector, SelectorIDs.size()}).first;
150 return Known->second;
154 void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
155 void writeControlBlock(llvm::BitstreamWriter &Stream);
156 void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
157 void writeContextBlock(llvm::BitstreamWriter &Stream);
158 void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
159 void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
160 void writeCXXMethodBlock(llvm::BitstreamWriter &Stream);
161 void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
162 void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
163 void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
164 void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
165 void writeTagBlock(llvm::BitstreamWriter &Stream);
166 void writeTypedefBlock(llvm::BitstreamWriter &Stream);
170 : ModuleName(
std::string(ModuleName)), SourceFile(SF) {}
179 llvm::BitstreamWriter Stream(Buffer);
183 Stream.Emit(Byte, 8);
186 writeBlockInfoBlock(Stream);
187 writeControlBlock(Stream);
188 writeIdentifierBlock(Stream);
189 writeContextBlock(Stream);
190 writeObjCPropertyBlock(Stream);
191 writeObjCMethodBlock(Stream);
192 writeCXXMethodBlock(Stream);
193 writeObjCSelectorBlock(Stream);
194 writeGlobalVariableBlock(Stream);
195 writeGlobalFunctionBlock(Stream);
196 writeEnumConstantBlock(Stream);
197 writeTagBlock(Stream);
198 writeTypedefBlock(Stream);
201 OS.write(Buffer.data(), Buffer.size());
208 llvm::StringRef Name) {
209 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
216 llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
218 const_cast<unsigned char *
>(
219 reinterpret_cast<const unsigned char *
>(Name.data())),
225 llvm::StringRef Name) {
226 assert(
ID < 256 &&
"can't fit record ID in next to name");
229 Buffer.resize(Name.size() + 1);
231 memcpy(Buffer.data() + 1, Name.data(), Name.size());
233 Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
237void APINotesWriter::Implementation::writeBlockInfoBlock(
238 llvm::BitstreamWriter &Stream) {
239 llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
241#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
242#define BLOCK_RECORD(NameSpace, Block) \
243 emitRecordID(Stream, NameSpace::Block, #Block)
244 BLOCK(CONTROL_BLOCK);
248 BLOCK(IDENTIFIER_BLOCK);
251 BLOCK(OBJC_CONTEXT_BLOCK);
254 BLOCK(OBJC_PROPERTY_BLOCK);
257 BLOCK(OBJC_METHOD_BLOCK);
260 BLOCK(OBJC_SELECTOR_BLOCK);
263 BLOCK(GLOBAL_VARIABLE_BLOCK);
264 BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
266 BLOCK(GLOBAL_FUNCTION_BLOCK);
267 BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
272void APINotesWriter::Implementation::writeControlBlock(
273 llvm::BitstreamWriter &Stream) {
280 ModuleName.emit(Scratch, this->ModuleName);
284 SourceFile.emit(Scratch, this->SourceFile->
getSize(),
285 this->SourceFile->getModificationTime());
291class IdentifierTableInfo {
293 using key_type = StringRef;
294 using key_type_ref = key_type;
296 using data_type_ref =
const data_type &;
297 using hash_value_type = uint32_t;
300 hash_value_type
ComputeHash(key_type_ref Key) {
return llvm::djbHash(Key); }
302 std::pair<unsigned, unsigned>
303 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
304 uint32_t KeyLength = Key.size();
305 uint32_t DataLength =
sizeof(uint32_t);
307 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
308 writer.write<uint16_t>(KeyLength);
309 writer.write<uint16_t>(DataLength);
310 return {KeyLength, DataLength};
313 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) { OS << Key; }
315 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
316 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
317 writer.write<uint32_t>(
Data);
322void APINotesWriter::Implementation::writeIdentifierBlock(
323 llvm::BitstreamWriter &Stream) {
326 if (IdentifierIDs.empty())
332 llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo>
Generator;
333 for (
auto &II : IdentifierIDs)
336 llvm::raw_svector_ostream BlobStream(HashTableBlob);
338 llvm::support::endian::write<uint32_t>(BlobStream, 0,
339 llvm::endianness::little);
344 IdentifierData.emit(Scratch, Offset, HashTableBlob);
349class ContextIDTableInfo {
351 using key_type = ContextTableKey;
352 using key_type_ref = key_type;
354 using data_type_ref =
const data_type &;
355 using hash_value_type =
size_t;
359 return static_cast<size_t>(Key.hashValue());
362 std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
364 uint32_t KeyLength =
sizeof(uint32_t) +
sizeof(uint8_t) +
sizeof(uint32_t);
365 uint32_t DataLength =
sizeof(uint32_t);
367 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
368 writer.write<uint16_t>(KeyLength);
369 writer.write<uint16_t>(DataLength);
370 return {KeyLength, DataLength};
373 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
374 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
375 writer.write<uint32_t>(Key.parentContextID);
376 writer.write<uint8_t>(Key.contextKind);
377 writer.write<uint32_t>(Key.contextID);
380 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
381 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
382 writer.write<uint32_t>(
Data);
388template <
typename T>
struct MakeDependent {
typedef T Type; };
392unsigned getVersionTupleSize(
const VersionTuple &VT) {
393 unsigned size =
sizeof(uint8_t) +
sizeof(uint32_t);
395 size +=
sizeof(uint32_t);
396 if (VT.getSubminor())
397 size +=
sizeof(uint32_t);
399 size +=
sizeof(uint32_t);
405unsigned getVersionedInfoSize(
407 llvm::function_ref<
unsigned(
const typename MakeDependent<T>::Type &)>
409 unsigned result =
sizeof(uint16_t);
410 for (
const auto &
E : VI) {
411 result += getVersionTupleSize(
E.first);
412 result += getInfoSize(
E.second);
418void emitVersionTuple(raw_ostream &OS,
const VersionTuple &VT) {
419 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
425 else if (VT.getSubminor())
427 else if (VT.getMinor())
431 writer.write<uint8_t>(descriptor);
434 writer.write<uint32_t>(VT.getMajor());
435 if (
auto minor = VT.getMinor())
436 writer.write<uint32_t>(*minor);
437 if (
auto subminor = VT.getSubminor())
438 writer.write<uint32_t>(*subminor);
439 if (
auto build = VT.getBuild())
440 writer.write<uint32_t>(*build);
445void emitVersionedInfo(
447 llvm::function_ref<
void(raw_ostream &,
448 const typename MakeDependent<T>::Type &)>
450 std::sort(VI.begin(), VI.end(),
451 [](
const std::pair<VersionTuple, T> &LHS,
452 const std::pair<VersionTuple, T> &RHS) ->
bool {
453 assert((&LHS == &RHS || LHS.first != RHS.first) &&
454 "two entries for the same version");
455 return LHS.first < RHS.first;
458 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
459 writer.write<uint16_t>(VI.size());
460 for (
const auto &
E : VI) {
461 emitVersionTuple(OS,
E.first);
462 emitInfo(OS,
E.second);
467template <
typename Derived,
typename KeyType,
typename UnversionedDataType>
468class VersionedTableInfo {
469 Derived &asDerived() {
return *
static_cast<Derived *
>(
this); }
471 const Derived &asDerived()
const {
472 return *
static_cast<const Derived *
>(
this);
476 using key_type = KeyType;
477 using key_type_ref = key_type;
480 using data_type_ref = data_type &;
481 using hash_value_type =
size_t;
484 std::pair<unsigned, unsigned>
485 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref
Data) {
486 uint32_t KeyLength = asDerived().getKeyLength(Key);
487 uint32_t DataLength =
488 getVersionedInfoSize(
Data, [
this](
const UnversionedDataType &UI) {
489 return asDerived().getUnversionedInfoSize(UI);
492 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
493 writer.write<uint16_t>(KeyLength);
494 writer.write<uint16_t>(DataLength);
495 return {KeyLength, DataLength};
498 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
500 OS,
Data, [
this](llvm::raw_ostream &OS,
const UnversionedDataType &UI) {
501 asDerived().emitUnversionedInfo(OS, UI);
507void emitCommonEntityInfo(raw_ostream &OS,
const CommonEntityInfo &CEI) {
508 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
511 if (
auto swiftPrivate = CEI.isSwiftPrivate()) {
517 payload |= CEI.Unavailable;
519 payload |= CEI.UnavailableInSwift;
521 writer.write<uint8_t>(payload);
523 writer.write<uint16_t>(CEI.UnavailableMsg.size());
524 OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
526 writer.write<uint16_t>(CEI.SwiftName.size());
527 OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
532unsigned getCommonEntityInfoSize(
const CommonEntityInfo &CEI) {
533 return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
538unsigned getCommonTypeInfoSize(
const CommonTypeInfo &CTI) {
539 return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
540 (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
541 getCommonEntityInfoSize(CTI);
545void emitCommonTypeInfo(raw_ostream &OS,
const CommonTypeInfo &CTI) {
546 emitCommonEntityInfo(OS, CTI);
548 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
549 if (
auto swiftBridge = CTI.getSwiftBridge()) {
550 writer.write<uint16_t>(swiftBridge->size() + 1);
551 OS.write(swiftBridge->c_str(), swiftBridge->size());
553 writer.write<uint16_t>(0);
555 if (
auto nsErrorDomain = CTI.getNSErrorDomain()) {
556 writer.write<uint16_t>(nsErrorDomain->size() + 1);
557 OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
559 writer.write<uint16_t>(0);
564class ContextInfoTableInfo
565 :
public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
567 unsigned getKeyLength(key_type_ref) {
return sizeof(uint32_t); }
569 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
570 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
571 writer.write<uint32_t>(Key);
578 unsigned getUnversionedInfoSize(
const ContextInfo &OCI) {
579 return getCommonTypeInfoSize(OCI) + 1;
582 void emitUnversionedInfo(raw_ostream &OS,
const ContextInfo &OCI) {
583 emitCommonTypeInfo(OS, OCI);
586 if (
auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
587 payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
589 if (
auto swiftObjCMembers = OCI.getSwiftObjCMembers())
590 payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
592 if (
auto nullable = OCI.getDefaultNullability())
593 payload |= (0x01 << 2) |
static_cast<uint8_t
>(*nullable);
594 payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
601void APINotesWriter::Implementation::writeContextBlock(
602 llvm::BitstreamWriter &Stream) {
605 if (Contexts.empty())
612 llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo>
Generator;
613 for (
auto &OC : Contexts)
614 Generator.insert(OC.first, OC.second.first);
616 llvm::raw_svector_ostream BlobStream(HashTableBlob);
618 llvm::support::endian::write<uint32_t>(BlobStream, 0,
619 llvm::endianness::little);
624 ContextID.emit(Scratch, Offset, HashTableBlob);
631 llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo>
Generator;
632 for (
auto &OC : Contexts)
633 Generator.insert(OC.second.first, OC.second.second);
635 llvm::raw_svector_ostream BlobStream(HashTableBlob);
637 llvm::support::endian::write<uint32_t>(BlobStream, 0,
638 llvm::endianness::little);
643 ContextInfo.emit(Scratch, Offset, HashTableBlob);
650unsigned getVariableInfoSize(
const VariableInfo &VI) {
651 return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
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 &);
743class ObjCMethodTableInfo
744 :
public VersionedTableInfo<ObjCMethodTableInfo,
745 std::tuple<unsigned, unsigned, char>,
748 unsigned getKeyLength(key_type_ref) {
749 return sizeof(uint32_t) +
sizeof(uint32_t) +
sizeof(uint8_t);
752 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
753 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
754 writer.write<uint32_t>(std::get<0>(Key));
755 writer.write<uint32_t>(std::get<1>(Key));
756 writer.write<uint8_t>(std::get<2>(Key));
763 unsigned getUnversionedInfoSize(
const ObjCMethodInfo &OMI) {
764 return getFunctionInfoSize(OMI) + 1;
767 void emitUnversionedInfo(raw_ostream &OS,
const ObjCMethodInfo &OMI) {
769 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
770 flags = (flags << 1) | OMI.DesignatedInit;
771 flags = (flags << 1) | OMI.RequiredInit;
772 writer.write<uint8_t>(flags);
774 emitFunctionInfo(OS, OMI);
779class CXXMethodTableInfo
780 :
public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
783 unsigned getKeyLength(key_type_ref) {
784 return sizeof(uint32_t) +
sizeof(uint32_t);
787 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
788 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
789 writer.write<uint32_t>(Key.parentContextID);
790 writer.write<uint32_t>(Key.nameID);
794 return static_cast<size_t>(key.hashValue());
797 unsigned getUnversionedInfoSize(
const CXXMethodInfo &OMI) {
798 return getFunctionInfoSize(OMI);
801 void emitUnversionedInfo(raw_ostream &OS,
const CXXMethodInfo &OMI) {
802 emitFunctionInfo(OS, OMI);
807void APINotesWriter::Implementation::writeObjCMethodBlock(
808 llvm::BitstreamWriter &Stream) {
811 if (ObjCMethods.empty())
818 llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo>
Generator;
819 for (
auto &OM : ObjCMethods)
822 llvm::raw_svector_ostream BlobStream(HashTableBlob);
824 llvm::support::endian::write<uint32_t>(BlobStream, 0,
825 llvm::endianness::little);
830 ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
834void APINotesWriter::Implementation::writeCXXMethodBlock(
835 llvm::BitstreamWriter &Stream) {
838 if (CXXMethods.empty())
845 llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo>
Generator;
846 for (
auto &MD : CXXMethods)
849 llvm::raw_svector_ostream BlobStream(HashTableBlob);
851 llvm::support::endian::write<uint32_t>(BlobStream, 0,
852 llvm::endianness::little);
857 CXXMethodData.emit(Scratch, Offset, HashTableBlob);
863class ObjCSelectorTableInfo {
865 using key_type = StoredObjCSelector;
866 using key_type_ref =
const key_type &;
868 using data_type_ref = data_type;
873 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
876 std::pair<unsigned, unsigned>
877 EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
879 sizeof(uint16_t) +
sizeof(uint32_t) * Key.Identifiers.size();
880 uint32_t DataLength =
sizeof(uint32_t);
882 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
883 writer.write<uint16_t>(KeyLength);
884 writer.write<uint16_t>(DataLength);
885 return {KeyLength, DataLength};
888 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
889 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
890 writer.write<uint16_t>(Key.NumArgs);
895 void EmitData(raw_ostream &OS, key_type_ref, data_type_ref
Data,
unsigned) {
896 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
897 writer.write<uint32_t>(
Data);
902void APINotesWriter::Implementation::writeObjCSelectorBlock(
903 llvm::BitstreamWriter &Stream) {
906 if (SelectorIDs.empty())
913 llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo>
Generator;
914 for (
auto &S : SelectorIDs)
917 llvm::raw_svector_ostream BlobStream(HashTableBlob);
919 llvm::support::endian::write<uint32_t>(BlobStream, 0,
920 llvm::endianness::little);
925 ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
931class GlobalVariableTableInfo
932 :
public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
933 GlobalVariableInfo> {
935 unsigned getKeyLength(key_type_ref) {
936 return sizeof(uint32_t) +
sizeof(uint32_t);
939 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
940 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
941 writer.write<uint32_t>(Key.parentContextID);
942 writer.write<uint32_t>(Key.nameID);
946 return static_cast<size_t>(Key.hashValue());
949 unsigned getUnversionedInfoSize(
const GlobalVariableInfo &GVI) {
950 return getVariableInfoSize(GVI);
953 void emitUnversionedInfo(raw_ostream &OS,
const GlobalVariableInfo &GVI) {
954 emitVariableInfo(OS, GVI);
959void APINotesWriter::Implementation::writeGlobalVariableBlock(
960 llvm::BitstreamWriter &Stream) {
963 if (GlobalVariables.empty())
970 llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo>
Generator;
971 for (
auto &GV : GlobalVariables)
974 llvm::raw_svector_ostream BlobStream(HashTableBlob);
976 llvm::support::endian::write<uint32_t>(BlobStream, 0,
977 llvm::endianness::little);
982 GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
987unsigned getParamInfoSize(
const ParamInfo &PI) {
988 return getVariableInfoSize(PI) + 1;
991void emitParamInfo(raw_ostream &OS,
const ParamInfo &PI) {
992 emitVariableInfo(OS, PI);
995 if (
auto noescape = PI.isNoEscape()) {
1001 if (
auto RCC = PI.getRetainCountConvention())
1002 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1004 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1005 writer.write<uint8_t>(flags);
1010unsigned getFunctionInfoSize(
const FunctionInfo &FI) {
1011 unsigned size = getCommonEntityInfoSize(FI) + 2 +
sizeof(
uint64_t);
1012 size +=
sizeof(uint16_t);
1013 for (
const auto &
P : FI.Params)
1014 size += getParamInfoSize(
P);
1015 size +=
sizeof(uint16_t) + FI.ResultType.size();
1020void emitFunctionInfo(raw_ostream &OS,
const FunctionInfo &FI) {
1021 emitCommonEntityInfo(OS, FI);
1024 flags |= FI.NullabilityAudited;
1026 if (
auto RCC = FI.getRetainCountConvention())
1027 flags |=
static_cast<uint8_t
>(RCC.value()) + 1;
1029 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1031 writer.write<uint8_t>(flags);
1032 writer.write<uint8_t>(FI.NumAdjustedNullable);
1033 writer.write<
uint64_t>(FI.NullabilityPayload);
1035 writer.write<uint16_t>(FI.Params.size());
1036 for (
const auto &PI : FI.Params)
1037 emitParamInfo(OS, PI);
1039 writer.write<uint16_t>(FI.ResultType.size());
1040 writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
1044class GlobalFunctionTableInfo
1045 :
public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
1046 GlobalFunctionInfo> {
1048 unsigned getKeyLength(key_type_ref) {
1049 return sizeof(uint32_t) +
sizeof(uint32_t);
1052 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1053 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1054 writer.write<uint32_t>(Key.parentContextID);
1055 writer.write<uint32_t>(Key.nameID);
1059 return static_cast<size_t>(Key.hashValue());
1062 unsigned getUnversionedInfoSize(
const GlobalFunctionInfo &GFI) {
1063 return getFunctionInfoSize(GFI);
1066 void emitUnversionedInfo(raw_ostream &OS,
const GlobalFunctionInfo &GFI) {
1067 emitFunctionInfo(OS, GFI);
1072void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1073 llvm::BitstreamWriter &Stream) {
1076 if (GlobalFunctions.empty())
1083 llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo>
Generator;
1084 for (
auto &F : GlobalFunctions)
1087 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1089 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1090 llvm::endianness::little);
1095 GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1101class EnumConstantTableInfo
1102 :
public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1105 unsigned getKeyLength(key_type_ref) {
return sizeof(uint32_t); }
1107 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1108 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1109 writer.write<uint32_t>(Key);
1116 unsigned getUnversionedInfoSize(
const EnumConstantInfo &ECI) {
1117 return getCommonEntityInfoSize(ECI);
1120 void emitUnversionedInfo(raw_ostream &OS,
const EnumConstantInfo &ECI) {
1121 emitCommonEntityInfo(OS, ECI);
1126void APINotesWriter::Implementation::writeEnumConstantBlock(
1127 llvm::BitstreamWriter &Stream) {
1130 if (EnumConstants.empty())
1137 llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo>
Generator;
1138 for (
auto &EC : EnumConstants)
1141 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1143 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1144 llvm::endianness::little);
1149 EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1154template <
typename Derived,
typename UnversionedDataType>
1155class CommonTypeTableInfo
1156 :
public VersionedTableInfo<Derived, SingleDeclTableKey,
1157 UnversionedDataType> {
1159 using key_type_ref =
typename CommonTypeTableInfo::key_type_ref;
1160 using hash_value_type =
typename CommonTypeTableInfo::hash_value_type;
1162 unsigned getKeyLength(key_type_ref) {
1163 return sizeof(uint32_t) +
sizeof(IdentifierID);
1166 void EmitKey(raw_ostream &OS, key_type_ref Key,
unsigned) {
1167 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1168 writer.write<uint32_t>(Key.parentContextID);
1173 return static_cast<size_t>(Key.hashValue());
1176 unsigned getUnversionedInfoSize(
const UnversionedDataType &UDT) {
1177 return getCommonTypeInfoSize(UDT);
1180 void emitUnversionedInfo(raw_ostream &OS,
const UnversionedDataType &UDT) {
1181 emitCommonTypeInfo(OS, UDT);
1186class TagTableInfo :
public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1188 unsigned getUnversionedInfoSize(
const TagInfo &TI) {
1189 return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1190 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1191 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1192 2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
1193 2 + getCommonTypeInfoSize(TI);
1196 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1197 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1200 if (
auto extensibility = TI.EnumExtensibility) {
1201 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1202 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1206 if (
auto value = TI.isFlagEnum())
1207 Flags |= (value.value() << 1 | 1 << 0);
1209 writer.write<uint8_t>(Flags);
1211 if (
auto Copyable = TI.isSwiftCopyable())
1212 writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
1214 writer.write<uint8_t>(0);
1216 if (
auto ImportAs = TI.SwiftImportAs) {
1217 writer.write<uint16_t>(ImportAs->size() + 1);
1218 OS.write(ImportAs->c_str(), ImportAs->size());
1220 writer.write<uint16_t>(0);
1222 if (
auto RetainOp = TI.SwiftRetainOp) {
1223 writer.write<uint16_t>(RetainOp->size() + 1);
1224 OS.write(RetainOp->c_str(), RetainOp->size());
1226 writer.write<uint16_t>(0);
1228 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1229 writer.write<uint16_t>(ReleaseOp->size() + 1);
1230 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1232 writer.write<uint16_t>(0);
1234 if (
auto Conformance = TI.SwiftConformance) {
1235 writer.write<uint16_t>(Conformance->size() + 1);
1236 OS.write(Conformance->c_str(), Conformance->size());
1238 writer.write<uint16_t>(0);
1241 emitCommonTypeInfo(OS, TI);
1246void APINotesWriter::Implementation::writeTagBlock(
1247 llvm::BitstreamWriter &Stream) {
1257 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1258 for (
auto &
T : Tags)
1261 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1263 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1264 llvm::endianness::little);
1269 TagData.emit(Scratch, Offset, HashTableBlob);
1275class TypedefTableInfo
1276 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1278 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1279 return 1 + getCommonTypeInfoSize(TI);
1282 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1283 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1286 if (
auto swiftWrapper = TI.SwiftWrapper)
1287 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1289 writer.write<uint8_t>(Flags);
1291 emitCommonTypeInfo(OS, TI);
1296void APINotesWriter::Implementation::writeTypedefBlock(
1297 llvm::BitstreamWriter &Stream) {
1300 if (Typedefs.empty())
1307 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1308 for (
auto &
T : Typedefs)
1311 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1313 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1314 llvm::endianness::little);
1319 TypedefData.emit(Scratch, Offset, HashTableBlob);
1337 llvm::VersionTuple SwiftVersion) {
1340 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1348 .insert(std::make_pair(
1349 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1357 auto &VersionedVec = Known->second.second;
1359 for (
auto &Versioned : VersionedVec) {
1360 if (Versioned.first == SwiftVersion) {
1361 Versioned.second |= Info;
1368 VersionedVec.push_back({SwiftVersion, Info});
1374 bool IsInstanceProperty,
1376 VersionTuple SwiftVersion) {
1379 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1380 .push_back({SwiftVersion, Info});
1384 bool IsInstanceMethod,
1386 VersionTuple SwiftVersion) {
1388 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1390 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1403 for (
auto &Versioned : VersionedVec) {
1404 if (Versioned.first == SwiftVersion) {
1405 Versioned.second.setHasDesignatedInits(
true);
1412 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1413 VersionedVec.back().second.setHasDesignatedInits(
true);
1420 VersionTuple SwiftVersion) {
1427 llvm::StringRef Name,
1429 VersionTuple SwiftVersion) {
1432 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1436 llvm::StringRef Name,
1438 VersionTuple SwiftVersion) {
1441 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1446 VersionTuple SwiftVersion) {
1448 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1452 const TagInfo &Info, VersionTuple SwiftVersion) {
1460 VersionTuple SwiftVersion) {
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
enum clang::sema::@1658::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 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 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< 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,...
@ 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.