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 + getCommonTypeInfoSize(TI);
1195 void emitUnversionedInfo(raw_ostream &OS,
const TagInfo &TI) {
1196 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1199 if (
auto extensibility = TI.EnumExtensibility) {
1200 Flags |=
static_cast<uint8_t
>(extensibility.value()) + 1;
1201 assert((Flags < (1 << 2)) &&
"must fit in two bits");
1205 if (
auto value = TI.isFlagEnum())
1206 Flags |= (value.value() << 1 | 1 << 0);
1208 writer.write<uint8_t>(Flags);
1210 if (
auto Copyable = TI.isSwiftCopyable())
1211 writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
1213 writer.write<uint8_t>(0);
1215 if (
auto ImportAs = TI.SwiftImportAs) {
1216 writer.write<uint16_t>(ImportAs->size() + 1);
1217 OS.write(ImportAs->c_str(), ImportAs->size());
1219 writer.write<uint16_t>(0);
1221 if (
auto RetainOp = TI.SwiftRetainOp) {
1222 writer.write<uint16_t>(RetainOp->size() + 1);
1223 OS.write(RetainOp->c_str(), RetainOp->size());
1225 writer.write<uint16_t>(0);
1227 if (
auto ReleaseOp = TI.SwiftReleaseOp) {
1228 writer.write<uint16_t>(ReleaseOp->size() + 1);
1229 OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1231 writer.write<uint16_t>(0);
1234 emitCommonTypeInfo(OS, TI);
1239void APINotesWriter::Implementation::writeTagBlock(
1240 llvm::BitstreamWriter &Stream) {
1250 llvm::OnDiskChainedHashTableGenerator<TagTableInfo>
Generator;
1251 for (
auto &
T : Tags)
1254 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1256 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1257 llvm::endianness::little);
1262 TagData.emit(Scratch, Offset, HashTableBlob);
1268class TypedefTableInfo
1269 :
public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1271 unsigned getUnversionedInfoSize(
const TypedefInfo &TI) {
1272 return 1 + getCommonTypeInfoSize(TI);
1275 void emitUnversionedInfo(raw_ostream &OS,
const TypedefInfo &TI) {
1276 llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1279 if (
auto swiftWrapper = TI.SwiftWrapper)
1280 Flags |=
static_cast<uint8_t
>(*swiftWrapper) + 1;
1282 writer.write<uint8_t>(Flags);
1284 emitCommonTypeInfo(OS, TI);
1289void APINotesWriter::Implementation::writeTypedefBlock(
1290 llvm::BitstreamWriter &Stream) {
1293 if (Typedefs.empty())
1300 llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo>
Generator;
1301 for (
auto &
T : Typedefs)
1304 llvm::raw_svector_ostream BlobStream(HashTableBlob);
1306 llvm::support::endian::write<uint32_t>(BlobStream, 0,
1307 llvm::endianness::little);
1312 TypedefData.emit(Scratch, Offset, HashTableBlob);
1330 llvm::VersionTuple SwiftVersion) {
1333 uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1341 .insert(std::make_pair(
1342 Key, std::make_pair(NextID, EmptyVersionedInfo)))
1350 auto &VersionedVec = Known->second.second;
1352 for (
auto &Versioned : VersionedVec) {
1353 if (Versioned.first == SwiftVersion) {
1354 Versioned.second |= Info;
1361 VersionedVec.push_back({SwiftVersion, Info});
1367 bool IsInstanceProperty,
1369 VersionTuple SwiftVersion) {
1372 ->ObjCProperties[std::make_tuple(CtxID.
Value, NameID, IsInstanceProperty)]
1373 .push_back({SwiftVersion, Info});
1377 bool IsInstanceMethod,
1379 VersionTuple SwiftVersion) {
1381 auto Key = std::tuple<unsigned, unsigned, char>{CtxID.
Value, SelID,
1383 Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1396 for (
auto &Versioned : VersionedVec) {
1397 if (Versioned.first == SwiftVersion) {
1398 Versioned.second.setHasDesignatedInits(
true);
1405 VersionedVec.push_back({SwiftVersion,
ContextInfo()});
1406 VersionedVec.back().second.setHasDesignatedInits(
true);
1413 VersionTuple SwiftVersion) {
1420 llvm::StringRef Name,
1422 VersionTuple SwiftVersion) {
1425 Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1429 llvm::StringRef Name,
1431 VersionTuple SwiftVersion) {
1434 Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1439 VersionTuple SwiftVersion) {
1441 Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1445 const TagInfo &Info, VersionTuple SwiftVersion) {
1453 VersionTuple SwiftVersion) {
#define BLOCK_RECORD(NameSpace, Block)
static StringRef bytes(const std::vector< T, Allocator > &v)
enum clang::sema::@1651::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.