15f757f3fSDimitry Andric //===-- APINotesWriter.cpp - API Notes Writer -------------------*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #include "clang/APINotes/APINotesWriter.h" 105f757f3fSDimitry Andric #include "APINotesFormat.h" 115f757f3fSDimitry Andric #include "clang/APINotes/Types.h" 125f757f3fSDimitry Andric #include "clang/Basic/FileManager.h" 135f757f3fSDimitry Andric #include "llvm/ADT/DenseMap.h" 145f757f3fSDimitry Andric #include "llvm/ADT/StringMap.h" 155f757f3fSDimitry Andric #include "llvm/Bitstream/BitstreamWriter.h" 165f757f3fSDimitry Andric #include "llvm/Support/DJB.h" 175f757f3fSDimitry Andric #include "llvm/Support/OnDiskHashTable.h" 185f757f3fSDimitry Andric #include "llvm/Support/VersionTuple.h" 195f757f3fSDimitry Andric 205f757f3fSDimitry Andric namespace clang { 215f757f3fSDimitry Andric namespace api_notes { 225f757f3fSDimitry Andric class APINotesWriter::Implementation { 235f757f3fSDimitry Andric friend class APINotesWriter; 245f757f3fSDimitry Andric 255f757f3fSDimitry Andric template <typename T> 265f757f3fSDimitry Andric using VersionedSmallVector = 275f757f3fSDimitry Andric llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1>; 285f757f3fSDimitry Andric 295f757f3fSDimitry Andric std::string ModuleName; 305f757f3fSDimitry Andric const FileEntry *SourceFile; 315f757f3fSDimitry Andric 325f757f3fSDimitry Andric /// Scratch space for bitstream writing. 335f757f3fSDimitry Andric llvm::SmallVector<uint64_t, 64> Scratch; 345f757f3fSDimitry Andric 355f757f3fSDimitry Andric /// Mapping from strings to identifier IDs. 365f757f3fSDimitry Andric llvm::StringMap<IdentifierID> IdentifierIDs; 375f757f3fSDimitry Andric 385f757f3fSDimitry Andric /// Information about contexts (Objective-C classes or protocols or C++ 395f757f3fSDimitry Andric /// namespaces). 405f757f3fSDimitry Andric /// 415f757f3fSDimitry Andric /// Indexed by the parent context ID, context kind and the identifier ID of 425f757f3fSDimitry Andric /// this context and provides both the context ID and information describing 435f757f3fSDimitry Andric /// the context within that module. 445f757f3fSDimitry Andric llvm::DenseMap<ContextTableKey, 45*0fca6ea1SDimitry Andric std::pair<unsigned, VersionedSmallVector<ContextInfo>>> 46*0fca6ea1SDimitry Andric Contexts; 475f757f3fSDimitry Andric 485f757f3fSDimitry Andric /// Information about parent contexts for each context. 495f757f3fSDimitry Andric /// 505f757f3fSDimitry Andric /// Indexed by context ID, provides the parent context ID. 515f757f3fSDimitry Andric llvm::DenseMap<uint32_t, uint32_t> ParentContexts; 525f757f3fSDimitry Andric 535f757f3fSDimitry Andric /// Mapping from context IDs to the identifier ID holding the name. 54*0fca6ea1SDimitry Andric llvm::DenseMap<unsigned, unsigned> ContextNames; 555f757f3fSDimitry Andric 565f757f3fSDimitry Andric /// Information about Objective-C properties. 575f757f3fSDimitry Andric /// 585f757f3fSDimitry Andric /// Indexed by the context ID, property name, and whether this is an 595f757f3fSDimitry Andric /// instance property. 605f757f3fSDimitry Andric llvm::DenseMap< 615f757f3fSDimitry Andric std::tuple<unsigned, unsigned, char>, 625f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, ObjCPropertyInfo>, 1>> 635f757f3fSDimitry Andric ObjCProperties; 645f757f3fSDimitry Andric 655f757f3fSDimitry Andric /// Information about Objective-C methods. 665f757f3fSDimitry Andric /// 675f757f3fSDimitry Andric /// Indexed by the context ID, selector ID, and Boolean (stored as a char) 685f757f3fSDimitry Andric /// indicating whether this is a class or instance method. 695f757f3fSDimitry Andric llvm::DenseMap<std::tuple<unsigned, unsigned, char>, 705f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, ObjCMethodInfo>, 1>> 715f757f3fSDimitry Andric ObjCMethods; 725f757f3fSDimitry Andric 73*0fca6ea1SDimitry Andric /// Information about C++ methods. 74*0fca6ea1SDimitry Andric /// 75*0fca6ea1SDimitry Andric /// Indexed by the context ID and name ID. 76*0fca6ea1SDimitry Andric llvm::DenseMap<SingleDeclTableKey, 77*0fca6ea1SDimitry Andric llvm::SmallVector<std::pair<VersionTuple, CXXMethodInfo>, 1>> 78*0fca6ea1SDimitry Andric CXXMethods; 79*0fca6ea1SDimitry Andric 805f757f3fSDimitry Andric /// Mapping from selectors to selector ID. 815f757f3fSDimitry Andric llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs; 825f757f3fSDimitry Andric 835f757f3fSDimitry Andric /// Information about global variables. 845f757f3fSDimitry Andric /// 85*0fca6ea1SDimitry Andric /// Indexed by the context ID, identifier ID. 865f757f3fSDimitry Andric llvm::DenseMap< 87*0fca6ea1SDimitry Andric SingleDeclTableKey, 885f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, GlobalVariableInfo>, 1>> 895f757f3fSDimitry Andric GlobalVariables; 905f757f3fSDimitry Andric 915f757f3fSDimitry Andric /// Information about global functions. 925f757f3fSDimitry Andric /// 93*0fca6ea1SDimitry Andric /// Indexed by the context ID, identifier ID. 945f757f3fSDimitry Andric llvm::DenseMap< 95*0fca6ea1SDimitry Andric SingleDeclTableKey, 965f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, GlobalFunctionInfo>, 1>> 975f757f3fSDimitry Andric GlobalFunctions; 985f757f3fSDimitry Andric 995f757f3fSDimitry Andric /// Information about enumerators. 1005f757f3fSDimitry Andric /// 1015f757f3fSDimitry Andric /// Indexed by the identifier ID. 1025f757f3fSDimitry Andric llvm::DenseMap< 1035f757f3fSDimitry Andric unsigned, llvm::SmallVector<std::pair<VersionTuple, EnumConstantInfo>, 1>> 1045f757f3fSDimitry Andric EnumConstants; 1055f757f3fSDimitry Andric 1065f757f3fSDimitry Andric /// Information about tags. 1075f757f3fSDimitry Andric /// 108*0fca6ea1SDimitry Andric /// Indexed by the context ID, identifier ID. 109*0fca6ea1SDimitry Andric llvm::DenseMap<SingleDeclTableKey, 1105f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, TagInfo>, 1>> 1115f757f3fSDimitry Andric Tags; 1125f757f3fSDimitry Andric 1135f757f3fSDimitry Andric /// Information about typedefs. 1145f757f3fSDimitry Andric /// 115*0fca6ea1SDimitry Andric /// Indexed by the context ID, identifier ID. 116*0fca6ea1SDimitry Andric llvm::DenseMap<SingleDeclTableKey, 1175f757f3fSDimitry Andric llvm::SmallVector<std::pair<VersionTuple, TypedefInfo>, 1>> 1185f757f3fSDimitry Andric Typedefs; 1195f757f3fSDimitry Andric 1205f757f3fSDimitry Andric /// Retrieve the ID for the given identifier. 1215f757f3fSDimitry Andric IdentifierID getIdentifier(StringRef Identifier) { 1225f757f3fSDimitry Andric if (Identifier.empty()) 1235f757f3fSDimitry Andric return 0; 1245f757f3fSDimitry Andric 1255f757f3fSDimitry Andric auto Known = IdentifierIDs.find(Identifier); 1265f757f3fSDimitry Andric if (Known != IdentifierIDs.end()) 1275f757f3fSDimitry Andric return Known->second; 1285f757f3fSDimitry Andric 1295f757f3fSDimitry Andric // Add to the identifier table. 1305f757f3fSDimitry Andric Known = IdentifierIDs.insert({Identifier, IdentifierIDs.size() + 1}).first; 1315f757f3fSDimitry Andric return Known->second; 1325f757f3fSDimitry Andric } 1335f757f3fSDimitry Andric 1345f757f3fSDimitry Andric /// Retrieve the ID for the given selector. 1355f757f3fSDimitry Andric SelectorID getSelector(ObjCSelectorRef SelectorRef) { 1365f757f3fSDimitry Andric // Translate the selector reference into a stored selector. 1375f757f3fSDimitry Andric StoredObjCSelector Selector; 138*0fca6ea1SDimitry Andric Selector.NumArgs = SelectorRef.NumArgs; 1395f757f3fSDimitry Andric Selector.Identifiers.reserve(SelectorRef.Identifiers.size()); 1405f757f3fSDimitry Andric for (auto piece : SelectorRef.Identifiers) 1415f757f3fSDimitry Andric Selector.Identifiers.push_back(getIdentifier(piece)); 1425f757f3fSDimitry Andric 1435f757f3fSDimitry Andric // Look for the stored selector. 1445f757f3fSDimitry Andric auto Known = SelectorIDs.find(Selector); 1455f757f3fSDimitry Andric if (Known != SelectorIDs.end()) 1465f757f3fSDimitry Andric return Known->second; 1475f757f3fSDimitry Andric 1485f757f3fSDimitry Andric // Add to the selector table. 1495f757f3fSDimitry Andric Known = SelectorIDs.insert({Selector, SelectorIDs.size()}).first; 1505f757f3fSDimitry Andric return Known->second; 1515f757f3fSDimitry Andric } 1525f757f3fSDimitry Andric 1535f757f3fSDimitry Andric private: 1545f757f3fSDimitry Andric void writeBlockInfoBlock(llvm::BitstreamWriter &Stream); 1555f757f3fSDimitry Andric void writeControlBlock(llvm::BitstreamWriter &Stream); 1565f757f3fSDimitry Andric void writeIdentifierBlock(llvm::BitstreamWriter &Stream); 157*0fca6ea1SDimitry Andric void writeContextBlock(llvm::BitstreamWriter &Stream); 1585f757f3fSDimitry Andric void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream); 1595f757f3fSDimitry Andric void writeObjCMethodBlock(llvm::BitstreamWriter &Stream); 160*0fca6ea1SDimitry Andric void writeCXXMethodBlock(llvm::BitstreamWriter &Stream); 1615f757f3fSDimitry Andric void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream); 1625f757f3fSDimitry Andric void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream); 1635f757f3fSDimitry Andric void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream); 1645f757f3fSDimitry Andric void writeEnumConstantBlock(llvm::BitstreamWriter &Stream); 1655f757f3fSDimitry Andric void writeTagBlock(llvm::BitstreamWriter &Stream); 1665f757f3fSDimitry Andric void writeTypedefBlock(llvm::BitstreamWriter &Stream); 1675f757f3fSDimitry Andric 1685f757f3fSDimitry Andric public: 1695f757f3fSDimitry Andric Implementation(llvm::StringRef ModuleName, const FileEntry *SF) 1705f757f3fSDimitry Andric : ModuleName(std::string(ModuleName)), SourceFile(SF) {} 1715f757f3fSDimitry Andric 1725f757f3fSDimitry Andric void writeToStream(llvm::raw_ostream &OS); 1735f757f3fSDimitry Andric }; 1745f757f3fSDimitry Andric 1755f757f3fSDimitry Andric void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) { 1765f757f3fSDimitry Andric llvm::SmallVector<char, 0> Buffer; 1775f757f3fSDimitry Andric 1785f757f3fSDimitry Andric { 1795f757f3fSDimitry Andric llvm::BitstreamWriter Stream(Buffer); 1805f757f3fSDimitry Andric 1815f757f3fSDimitry Andric // Emit the signature. 1825f757f3fSDimitry Andric for (unsigned char Byte : API_NOTES_SIGNATURE) 1835f757f3fSDimitry Andric Stream.Emit(Byte, 8); 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric // Emit the blocks. 1865f757f3fSDimitry Andric writeBlockInfoBlock(Stream); 1875f757f3fSDimitry Andric writeControlBlock(Stream); 1885f757f3fSDimitry Andric writeIdentifierBlock(Stream); 189*0fca6ea1SDimitry Andric writeContextBlock(Stream); 1905f757f3fSDimitry Andric writeObjCPropertyBlock(Stream); 1915f757f3fSDimitry Andric writeObjCMethodBlock(Stream); 192*0fca6ea1SDimitry Andric writeCXXMethodBlock(Stream); 1935f757f3fSDimitry Andric writeObjCSelectorBlock(Stream); 1945f757f3fSDimitry Andric writeGlobalVariableBlock(Stream); 1955f757f3fSDimitry Andric writeGlobalFunctionBlock(Stream); 1965f757f3fSDimitry Andric writeEnumConstantBlock(Stream); 1975f757f3fSDimitry Andric writeTagBlock(Stream); 1985f757f3fSDimitry Andric writeTypedefBlock(Stream); 1995f757f3fSDimitry Andric } 2005f757f3fSDimitry Andric 2015f757f3fSDimitry Andric OS.write(Buffer.data(), Buffer.size()); 2025f757f3fSDimitry Andric OS.flush(); 2035f757f3fSDimitry Andric } 2045f757f3fSDimitry Andric 2055f757f3fSDimitry Andric namespace { 2065f757f3fSDimitry Andric /// Record the name of a block. 2075f757f3fSDimitry Andric void emitBlockID(llvm::BitstreamWriter &Stream, unsigned ID, 2085f757f3fSDimitry Andric llvm::StringRef Name) { 2095f757f3fSDimitry Andric Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, 2105f757f3fSDimitry Andric llvm::ArrayRef<unsigned>{ID}); 2115f757f3fSDimitry Andric 2125f757f3fSDimitry Andric // Emit the block name if present. 2135f757f3fSDimitry Andric if (Name.empty()) 2145f757f3fSDimitry Andric return; 2155f757f3fSDimitry Andric Stream.EmitRecord( 2165f757f3fSDimitry Andric llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, 2175f757f3fSDimitry Andric llvm::ArrayRef<unsigned char>( 2185f757f3fSDimitry Andric const_cast<unsigned char *>( 2195f757f3fSDimitry Andric reinterpret_cast<const unsigned char *>(Name.data())), 2205f757f3fSDimitry Andric Name.size())); 2215f757f3fSDimitry Andric } 2225f757f3fSDimitry Andric 2235f757f3fSDimitry Andric /// Record the name of a record within a block. 2245f757f3fSDimitry Andric void emitRecordID(llvm::BitstreamWriter &Stream, unsigned ID, 2255f757f3fSDimitry Andric llvm::StringRef Name) { 2265f757f3fSDimitry Andric assert(ID < 256 && "can't fit record ID in next to name"); 2275f757f3fSDimitry Andric 2285f757f3fSDimitry Andric llvm::SmallVector<unsigned char, 64> Buffer; 2295f757f3fSDimitry Andric Buffer.resize(Name.size() + 1); 2305f757f3fSDimitry Andric Buffer[0] = ID; 2315f757f3fSDimitry Andric memcpy(Buffer.data() + 1, Name.data(), Name.size()); 2325f757f3fSDimitry Andric 2335f757f3fSDimitry Andric Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer); 2345f757f3fSDimitry Andric } 2355f757f3fSDimitry Andric } // namespace 2365f757f3fSDimitry Andric 2375f757f3fSDimitry Andric void APINotesWriter::Implementation::writeBlockInfoBlock( 2385f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 2395f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2); 2405f757f3fSDimitry Andric 2415f757f3fSDimitry Andric #define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block) 2425f757f3fSDimitry Andric #define BLOCK_RECORD(NameSpace, Block) \ 2435f757f3fSDimitry Andric emitRecordID(Stream, NameSpace::Block, #Block) 2445f757f3fSDimitry Andric BLOCK(CONTROL_BLOCK); 2455f757f3fSDimitry Andric BLOCK_RECORD(control_block, METADATA); 2465f757f3fSDimitry Andric BLOCK_RECORD(control_block, MODULE_NAME); 2475f757f3fSDimitry Andric 2485f757f3fSDimitry Andric BLOCK(IDENTIFIER_BLOCK); 2495f757f3fSDimitry Andric BLOCK_RECORD(identifier_block, IDENTIFIER_DATA); 2505f757f3fSDimitry Andric 2515f757f3fSDimitry Andric BLOCK(OBJC_CONTEXT_BLOCK); 252*0fca6ea1SDimitry Andric BLOCK_RECORD(context_block, CONTEXT_ID_DATA); 2535f757f3fSDimitry Andric 2545f757f3fSDimitry Andric BLOCK(OBJC_PROPERTY_BLOCK); 2555f757f3fSDimitry Andric BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA); 2565f757f3fSDimitry Andric 2575f757f3fSDimitry Andric BLOCK(OBJC_METHOD_BLOCK); 2585f757f3fSDimitry Andric BLOCK_RECORD(objc_method_block, OBJC_METHOD_DATA); 2595f757f3fSDimitry Andric 2605f757f3fSDimitry Andric BLOCK(OBJC_SELECTOR_BLOCK); 2615f757f3fSDimitry Andric BLOCK_RECORD(objc_selector_block, OBJC_SELECTOR_DATA); 2625f757f3fSDimitry Andric 2635f757f3fSDimitry Andric BLOCK(GLOBAL_VARIABLE_BLOCK); 2645f757f3fSDimitry Andric BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA); 2655f757f3fSDimitry Andric 2665f757f3fSDimitry Andric BLOCK(GLOBAL_FUNCTION_BLOCK); 2675f757f3fSDimitry Andric BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA); 2685f757f3fSDimitry Andric #undef BLOCK_RECORD 2695f757f3fSDimitry Andric #undef BLOCK 2705f757f3fSDimitry Andric } 2715f757f3fSDimitry Andric 2725f757f3fSDimitry Andric void APINotesWriter::Implementation::writeControlBlock( 2735f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 2745f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, CONTROL_BLOCK_ID, 3); 2755f757f3fSDimitry Andric 2765f757f3fSDimitry Andric control_block::MetadataLayout Metadata(Stream); 2775f757f3fSDimitry Andric Metadata.emit(Scratch, VERSION_MAJOR, VERSION_MINOR); 2785f757f3fSDimitry Andric 2795f757f3fSDimitry Andric control_block::ModuleNameLayout ModuleName(Stream); 2805f757f3fSDimitry Andric ModuleName.emit(Scratch, this->ModuleName); 2815f757f3fSDimitry Andric 2825f757f3fSDimitry Andric if (SourceFile) { 2835f757f3fSDimitry Andric control_block::SourceFileLayout SourceFile(Stream); 2845f757f3fSDimitry Andric SourceFile.emit(Scratch, this->SourceFile->getSize(), 2855f757f3fSDimitry Andric this->SourceFile->getModificationTime()); 2865f757f3fSDimitry Andric } 2875f757f3fSDimitry Andric } 2885f757f3fSDimitry Andric 2895f757f3fSDimitry Andric namespace { 2905f757f3fSDimitry Andric /// Used to serialize the on-disk identifier table. 2915f757f3fSDimitry Andric class IdentifierTableInfo { 2925f757f3fSDimitry Andric public: 2935f757f3fSDimitry Andric using key_type = StringRef; 2945f757f3fSDimitry Andric using key_type_ref = key_type; 2955f757f3fSDimitry Andric using data_type = IdentifierID; 2965f757f3fSDimitry Andric using data_type_ref = const data_type &; 2975f757f3fSDimitry Andric using hash_value_type = uint32_t; 2985f757f3fSDimitry Andric using offset_type = unsigned; 2995f757f3fSDimitry Andric 3005f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { return llvm::djbHash(Key); } 3015f757f3fSDimitry Andric 3025f757f3fSDimitry Andric std::pair<unsigned, unsigned> 3035f757f3fSDimitry Andric EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) { 3045f757f3fSDimitry Andric uint32_t KeyLength = Key.size(); 3055f757f3fSDimitry Andric uint32_t DataLength = sizeof(uint32_t); 3065f757f3fSDimitry Andric 3075f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 3085f757f3fSDimitry Andric writer.write<uint16_t>(KeyLength); 3095f757f3fSDimitry Andric writer.write<uint16_t>(DataLength); 3105f757f3fSDimitry Andric return {KeyLength, DataLength}; 3115f757f3fSDimitry Andric } 3125f757f3fSDimitry Andric 3135f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { OS << Key; } 3145f757f3fSDimitry Andric 3155f757f3fSDimitry Andric void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) { 3165f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 3175f757f3fSDimitry Andric writer.write<uint32_t>(Data); 3185f757f3fSDimitry Andric } 3195f757f3fSDimitry Andric }; 3205f757f3fSDimitry Andric } // namespace 3215f757f3fSDimitry Andric 3225f757f3fSDimitry Andric void APINotesWriter::Implementation::writeIdentifierBlock( 3235f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 3245f757f3fSDimitry Andric llvm::BCBlockRAII restoreBlock(Stream, IDENTIFIER_BLOCK_ID, 3); 3255f757f3fSDimitry Andric 3265f757f3fSDimitry Andric if (IdentifierIDs.empty()) 3275f757f3fSDimitry Andric return; 3285f757f3fSDimitry Andric 3295f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 3305f757f3fSDimitry Andric uint32_t Offset; 3315f757f3fSDimitry Andric { 3325f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo> Generator; 3335f757f3fSDimitry Andric for (auto &II : IdentifierIDs) 3345f757f3fSDimitry Andric Generator.insert(II.first(), II.second); 3355f757f3fSDimitry Andric 3365f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 3375f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 3385f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 3395f757f3fSDimitry Andric llvm::endianness::little); 3405f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 3415f757f3fSDimitry Andric } 3425f757f3fSDimitry Andric 3435f757f3fSDimitry Andric identifier_block::IdentifierDataLayout IdentifierData(Stream); 3445f757f3fSDimitry Andric IdentifierData.emit(Scratch, Offset, HashTableBlob); 3455f757f3fSDimitry Andric } 3465f757f3fSDimitry Andric 3475f757f3fSDimitry Andric namespace { 3485f757f3fSDimitry Andric /// Used to serialize the on-disk Objective-C context table. 349*0fca6ea1SDimitry Andric class ContextIDTableInfo { 3505f757f3fSDimitry Andric public: 3515f757f3fSDimitry Andric using key_type = ContextTableKey; 3525f757f3fSDimitry Andric using key_type_ref = key_type; 3535f757f3fSDimitry Andric using data_type = unsigned; 3545f757f3fSDimitry Andric using data_type_ref = const data_type &; 3555f757f3fSDimitry Andric using hash_value_type = size_t; 3565f757f3fSDimitry Andric using offset_type = unsigned; 3575f757f3fSDimitry Andric 3585f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 3595f757f3fSDimitry Andric return static_cast<size_t>(Key.hashValue()); 3605f757f3fSDimitry Andric } 3615f757f3fSDimitry Andric 3625f757f3fSDimitry Andric std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref, 3635f757f3fSDimitry Andric data_type_ref) { 3645f757f3fSDimitry Andric uint32_t KeyLength = sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t); 3655f757f3fSDimitry Andric uint32_t DataLength = sizeof(uint32_t); 3665f757f3fSDimitry Andric 3675f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 3685f757f3fSDimitry Andric writer.write<uint16_t>(KeyLength); 3695f757f3fSDimitry Andric writer.write<uint16_t>(DataLength); 3705f757f3fSDimitry Andric return {KeyLength, DataLength}; 3715f757f3fSDimitry Andric } 3725f757f3fSDimitry Andric 3735f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 3745f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 3755f757f3fSDimitry Andric writer.write<uint32_t>(Key.parentContextID); 3765f757f3fSDimitry Andric writer.write<uint8_t>(Key.contextKind); 3775f757f3fSDimitry Andric writer.write<uint32_t>(Key.contextID); 3785f757f3fSDimitry Andric } 3795f757f3fSDimitry Andric 3805f757f3fSDimitry Andric void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) { 3815f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 3825f757f3fSDimitry Andric writer.write<uint32_t>(Data); 3835f757f3fSDimitry Andric } 3845f757f3fSDimitry Andric }; 3855f757f3fSDimitry Andric 3865f757f3fSDimitry Andric /// Localized helper to make a type dependent, thwarting template argument 3875f757f3fSDimitry Andric /// deduction. 3885f757f3fSDimitry Andric template <typename T> struct MakeDependent { typedef T Type; }; 3895f757f3fSDimitry Andric 3905f757f3fSDimitry Andric /// Retrieve the serialized size of the given VersionTuple, for use in 3915f757f3fSDimitry Andric /// on-disk hash tables. 3925f757f3fSDimitry Andric unsigned getVersionTupleSize(const VersionTuple &VT) { 3935f757f3fSDimitry Andric unsigned size = sizeof(uint8_t) + /*major*/ sizeof(uint32_t); 3945f757f3fSDimitry Andric if (VT.getMinor()) 3955f757f3fSDimitry Andric size += sizeof(uint32_t); 3965f757f3fSDimitry Andric if (VT.getSubminor()) 3975f757f3fSDimitry Andric size += sizeof(uint32_t); 3985f757f3fSDimitry Andric if (VT.getBuild()) 3995f757f3fSDimitry Andric size += sizeof(uint32_t); 4005f757f3fSDimitry Andric return size; 4015f757f3fSDimitry Andric } 4025f757f3fSDimitry Andric 4035f757f3fSDimitry Andric /// Determine the size of an array of versioned information, 4045f757f3fSDimitry Andric template <typename T> 4055f757f3fSDimitry Andric unsigned getVersionedInfoSize( 4065f757f3fSDimitry Andric const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI, 4075f757f3fSDimitry Andric llvm::function_ref<unsigned(const typename MakeDependent<T>::Type &)> 4085f757f3fSDimitry Andric getInfoSize) { 4095f757f3fSDimitry Andric unsigned result = sizeof(uint16_t); // # of elements 4105f757f3fSDimitry Andric for (const auto &E : VI) { 4115f757f3fSDimitry Andric result += getVersionTupleSize(E.first); 4125f757f3fSDimitry Andric result += getInfoSize(E.second); 4135f757f3fSDimitry Andric } 4145f757f3fSDimitry Andric return result; 4155f757f3fSDimitry Andric } 4165f757f3fSDimitry Andric 4175f757f3fSDimitry Andric /// Emit a serialized representation of a version tuple. 4185f757f3fSDimitry Andric void emitVersionTuple(raw_ostream &OS, const VersionTuple &VT) { 4195f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 4205f757f3fSDimitry Andric 4215f757f3fSDimitry Andric // First byte contains the number of components beyond the 'major' component. 4225f757f3fSDimitry Andric uint8_t descriptor; 4235f757f3fSDimitry Andric if (VT.getBuild()) 4245f757f3fSDimitry Andric descriptor = 3; 4255f757f3fSDimitry Andric else if (VT.getSubminor()) 4265f757f3fSDimitry Andric descriptor = 2; 4275f757f3fSDimitry Andric else if (VT.getMinor()) 4285f757f3fSDimitry Andric descriptor = 1; 4295f757f3fSDimitry Andric else 4305f757f3fSDimitry Andric descriptor = 0; 4315f757f3fSDimitry Andric writer.write<uint8_t>(descriptor); 4325f757f3fSDimitry Andric 4335f757f3fSDimitry Andric // Write the components. 4345f757f3fSDimitry Andric writer.write<uint32_t>(VT.getMajor()); 4355f757f3fSDimitry Andric if (auto minor = VT.getMinor()) 4365f757f3fSDimitry Andric writer.write<uint32_t>(*minor); 4375f757f3fSDimitry Andric if (auto subminor = VT.getSubminor()) 4385f757f3fSDimitry Andric writer.write<uint32_t>(*subminor); 4395f757f3fSDimitry Andric if (auto build = VT.getBuild()) 4405f757f3fSDimitry Andric writer.write<uint32_t>(*build); 4415f757f3fSDimitry Andric } 4425f757f3fSDimitry Andric 4435f757f3fSDimitry Andric /// Emit versioned information. 4445f757f3fSDimitry Andric template <typename T> 4455f757f3fSDimitry Andric void emitVersionedInfo( 4465f757f3fSDimitry Andric raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI, 4475f757f3fSDimitry Andric llvm::function_ref<void(raw_ostream &, 4485f757f3fSDimitry Andric const typename MakeDependent<T>::Type &)> 4495f757f3fSDimitry Andric emitInfo) { 4505f757f3fSDimitry Andric std::sort(VI.begin(), VI.end(), 4515f757f3fSDimitry Andric [](const std::pair<VersionTuple, T> &LHS, 4525f757f3fSDimitry Andric const std::pair<VersionTuple, T> &RHS) -> bool { 453*0fca6ea1SDimitry Andric assert((&LHS == &RHS || LHS.first != RHS.first) && 4545f757f3fSDimitry Andric "two entries for the same version"); 4555f757f3fSDimitry Andric return LHS.first < RHS.first; 4565f757f3fSDimitry Andric }); 4575f757f3fSDimitry Andric 4585f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 4595f757f3fSDimitry Andric writer.write<uint16_t>(VI.size()); 4605f757f3fSDimitry Andric for (const auto &E : VI) { 4615f757f3fSDimitry Andric emitVersionTuple(OS, E.first); 4625f757f3fSDimitry Andric emitInfo(OS, E.second); 4635f757f3fSDimitry Andric } 4645f757f3fSDimitry Andric } 4655f757f3fSDimitry Andric 4665f757f3fSDimitry Andric /// On-disk hash table info key base for handling versioned data. 4675f757f3fSDimitry Andric template <typename Derived, typename KeyType, typename UnversionedDataType> 4685f757f3fSDimitry Andric class VersionedTableInfo { 4695f757f3fSDimitry Andric Derived &asDerived() { return *static_cast<Derived *>(this); } 4705f757f3fSDimitry Andric 4715f757f3fSDimitry Andric const Derived &asDerived() const { 4725f757f3fSDimitry Andric return *static_cast<const Derived *>(this); 4735f757f3fSDimitry Andric } 4745f757f3fSDimitry Andric 4755f757f3fSDimitry Andric public: 4765f757f3fSDimitry Andric using key_type = KeyType; 4775f757f3fSDimitry Andric using key_type_ref = key_type; 4785f757f3fSDimitry Andric using data_type = 4795f757f3fSDimitry Andric llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>; 4805f757f3fSDimitry Andric using data_type_ref = data_type &; 4815f757f3fSDimitry Andric using hash_value_type = size_t; 4825f757f3fSDimitry Andric using offset_type = unsigned; 4835f757f3fSDimitry Andric 4845f757f3fSDimitry Andric std::pair<unsigned, unsigned> 4855f757f3fSDimitry Andric EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) { 4865f757f3fSDimitry Andric uint32_t KeyLength = asDerived().getKeyLength(Key); 4875f757f3fSDimitry Andric uint32_t DataLength = 4885f757f3fSDimitry Andric getVersionedInfoSize(Data, [this](const UnversionedDataType &UI) { 4895f757f3fSDimitry Andric return asDerived().getUnversionedInfoSize(UI); 4905f757f3fSDimitry Andric }); 4915f757f3fSDimitry Andric 4925f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 4935f757f3fSDimitry Andric writer.write<uint16_t>(KeyLength); 4945f757f3fSDimitry Andric writer.write<uint16_t>(DataLength); 4955f757f3fSDimitry Andric return {KeyLength, DataLength}; 4965f757f3fSDimitry Andric } 4975f757f3fSDimitry Andric 4985f757f3fSDimitry Andric void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) { 4995f757f3fSDimitry Andric emitVersionedInfo( 5005f757f3fSDimitry Andric OS, Data, [this](llvm::raw_ostream &OS, const UnversionedDataType &UI) { 5015f757f3fSDimitry Andric asDerived().emitUnversionedInfo(OS, UI); 5025f757f3fSDimitry Andric }); 5035f757f3fSDimitry Andric } 5045f757f3fSDimitry Andric }; 5055f757f3fSDimitry Andric 5065f757f3fSDimitry Andric /// Emit a serialized representation of the common entity information. 5075f757f3fSDimitry Andric void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) { 5085f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 5095f757f3fSDimitry Andric 5105f757f3fSDimitry Andric uint8_t payload = 0; 5115f757f3fSDimitry Andric if (auto swiftPrivate = CEI.isSwiftPrivate()) { 5125f757f3fSDimitry Andric payload |= 0x01; 5135f757f3fSDimitry Andric if (*swiftPrivate) 5145f757f3fSDimitry Andric payload |= 0x02; 5155f757f3fSDimitry Andric } 5165f757f3fSDimitry Andric payload <<= 1; 5175f757f3fSDimitry Andric payload |= CEI.Unavailable; 5185f757f3fSDimitry Andric payload <<= 1; 5195f757f3fSDimitry Andric payload |= CEI.UnavailableInSwift; 5205f757f3fSDimitry Andric 5215f757f3fSDimitry Andric writer.write<uint8_t>(payload); 5225f757f3fSDimitry Andric 5235f757f3fSDimitry Andric writer.write<uint16_t>(CEI.UnavailableMsg.size()); 5245f757f3fSDimitry Andric OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size()); 5255f757f3fSDimitry Andric 5265f757f3fSDimitry Andric writer.write<uint16_t>(CEI.SwiftName.size()); 5275f757f3fSDimitry Andric OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size()); 5285f757f3fSDimitry Andric } 5295f757f3fSDimitry Andric 5305f757f3fSDimitry Andric /// Retrieve the serialized size of the given CommonEntityInfo, for use in 5315f757f3fSDimitry Andric /// on-disk hash tables. 5325f757f3fSDimitry Andric unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) { 5335f757f3fSDimitry Andric return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size(); 5345f757f3fSDimitry Andric } 5355f757f3fSDimitry Andric 5365f757f3fSDimitry Andric // Retrieve the serialized size of the given CommonTypeInfo, for use 5375f757f3fSDimitry Andric // in on-disk hash tables. 5385f757f3fSDimitry Andric unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) { 5395f757f3fSDimitry Andric return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 + 5405f757f3fSDimitry Andric (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 5415f757f3fSDimitry Andric getCommonEntityInfoSize(CTI); 5425f757f3fSDimitry Andric } 5435f757f3fSDimitry Andric 5445f757f3fSDimitry Andric /// Emit a serialized representation of the common type information. 5455f757f3fSDimitry Andric void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) { 5465f757f3fSDimitry Andric emitCommonEntityInfo(OS, CTI); 5475f757f3fSDimitry Andric 5485f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 5495f757f3fSDimitry Andric if (auto swiftBridge = CTI.getSwiftBridge()) { 5505f757f3fSDimitry Andric writer.write<uint16_t>(swiftBridge->size() + 1); 5515f757f3fSDimitry Andric OS.write(swiftBridge->c_str(), swiftBridge->size()); 5525f757f3fSDimitry Andric } else { 5535f757f3fSDimitry Andric writer.write<uint16_t>(0); 5545f757f3fSDimitry Andric } 5555f757f3fSDimitry Andric if (auto nsErrorDomain = CTI.getNSErrorDomain()) { 5565f757f3fSDimitry Andric writer.write<uint16_t>(nsErrorDomain->size() + 1); 5575f757f3fSDimitry Andric OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size()); 5585f757f3fSDimitry Andric } else { 5595f757f3fSDimitry Andric writer.write<uint16_t>(0); 5605f757f3fSDimitry Andric } 5615f757f3fSDimitry Andric } 5625f757f3fSDimitry Andric 5635f757f3fSDimitry Andric /// Used to serialize the on-disk Objective-C property table. 564*0fca6ea1SDimitry Andric class ContextInfoTableInfo 565*0fca6ea1SDimitry Andric : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> { 5665f757f3fSDimitry Andric public: 5675f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); } 5685f757f3fSDimitry Andric 5695f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 5705f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 5715f757f3fSDimitry Andric writer.write<uint32_t>(Key); 5725f757f3fSDimitry Andric } 5735f757f3fSDimitry Andric 5745f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 5755f757f3fSDimitry Andric return static_cast<size_t>(llvm::hash_value(Key)); 5765f757f3fSDimitry Andric } 5775f757f3fSDimitry Andric 578*0fca6ea1SDimitry Andric unsigned getUnversionedInfoSize(const ContextInfo &OCI) { 5795f757f3fSDimitry Andric return getCommonTypeInfoSize(OCI) + 1; 5805f757f3fSDimitry Andric } 5815f757f3fSDimitry Andric 582*0fca6ea1SDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const ContextInfo &OCI) { 5835f757f3fSDimitry Andric emitCommonTypeInfo(OS, OCI); 5845f757f3fSDimitry Andric 5855f757f3fSDimitry Andric uint8_t payload = 0; 5865f757f3fSDimitry Andric if (auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric()) 5875f757f3fSDimitry Andric payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value(); 5885f757f3fSDimitry Andric payload <<= 2; 5895f757f3fSDimitry Andric if (auto swiftObjCMembers = OCI.getSwiftObjCMembers()) 5905f757f3fSDimitry Andric payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value(); 5915f757f3fSDimitry Andric payload <<= 3; 5925f757f3fSDimitry Andric if (auto nullable = OCI.getDefaultNullability()) 5935f757f3fSDimitry Andric payload |= (0x01 << 2) | static_cast<uint8_t>(*nullable); 5945f757f3fSDimitry Andric payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0); 5955f757f3fSDimitry Andric 5965f757f3fSDimitry Andric OS << payload; 5975f757f3fSDimitry Andric } 5985f757f3fSDimitry Andric }; 5995f757f3fSDimitry Andric } // namespace 6005f757f3fSDimitry Andric 601*0fca6ea1SDimitry Andric void APINotesWriter::Implementation::writeContextBlock( 6025f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 6035f757f3fSDimitry Andric llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3); 6045f757f3fSDimitry Andric 605*0fca6ea1SDimitry Andric if (Contexts.empty()) 6065f757f3fSDimitry Andric return; 6075f757f3fSDimitry Andric 6085f757f3fSDimitry Andric { 6095f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 6105f757f3fSDimitry Andric uint32_t Offset; 6115f757f3fSDimitry Andric { 612*0fca6ea1SDimitry Andric llvm::OnDiskChainedHashTableGenerator<ContextIDTableInfo> Generator; 613*0fca6ea1SDimitry Andric for (auto &OC : Contexts) 6145f757f3fSDimitry Andric Generator.insert(OC.first, OC.second.first); 6155f757f3fSDimitry Andric 6165f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 6175f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 6185f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 6195f757f3fSDimitry Andric llvm::endianness::little); 6205f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 6215f757f3fSDimitry Andric } 6225f757f3fSDimitry Andric 623*0fca6ea1SDimitry Andric context_block::ContextIDLayout ContextID(Stream); 624*0fca6ea1SDimitry Andric ContextID.emit(Scratch, Offset, HashTableBlob); 6255f757f3fSDimitry Andric } 6265f757f3fSDimitry Andric 6275f757f3fSDimitry Andric { 6285f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 6295f757f3fSDimitry Andric uint32_t Offset; 6305f757f3fSDimitry Andric { 631*0fca6ea1SDimitry Andric llvm::OnDiskChainedHashTableGenerator<ContextInfoTableInfo> Generator; 632*0fca6ea1SDimitry Andric for (auto &OC : Contexts) 6335f757f3fSDimitry Andric Generator.insert(OC.second.first, OC.second.second); 6345f757f3fSDimitry Andric 6355f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 6365f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 6375f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 6385f757f3fSDimitry Andric llvm::endianness::little); 6395f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 6405f757f3fSDimitry Andric } 6415f757f3fSDimitry Andric 642*0fca6ea1SDimitry Andric context_block::ContextInfoLayout ContextInfo(Stream); 643*0fca6ea1SDimitry Andric ContextInfo.emit(Scratch, Offset, HashTableBlob); 6445f757f3fSDimitry Andric } 6455f757f3fSDimitry Andric } 6465f757f3fSDimitry Andric 6475f757f3fSDimitry Andric namespace { 6485f757f3fSDimitry Andric /// Retrieve the serialized size of the given VariableInfo, for use in 6495f757f3fSDimitry Andric /// on-disk hash tables. 6505f757f3fSDimitry Andric unsigned getVariableInfoSize(const VariableInfo &VI) { 6515f757f3fSDimitry Andric return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size(); 6525f757f3fSDimitry Andric } 6535f757f3fSDimitry Andric 6545f757f3fSDimitry Andric /// Emit a serialized representation of the variable information. 6555f757f3fSDimitry Andric void emitVariableInfo(raw_ostream &OS, const VariableInfo &VI) { 6565f757f3fSDimitry Andric emitCommonEntityInfo(OS, VI); 6575f757f3fSDimitry Andric 6585f757f3fSDimitry Andric uint8_t bytes[2] = {0, 0}; 6595f757f3fSDimitry Andric if (auto nullable = VI.getNullability()) { 6605f757f3fSDimitry Andric bytes[0] = 1; 6615f757f3fSDimitry Andric bytes[1] = static_cast<uint8_t>(*nullable); 6625f757f3fSDimitry Andric } else { 6635f757f3fSDimitry Andric // Nothing to do. 6645f757f3fSDimitry Andric } 6655f757f3fSDimitry Andric 6665f757f3fSDimitry Andric OS.write(reinterpret_cast<const char *>(bytes), 2); 6675f757f3fSDimitry Andric 6685f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 6695f757f3fSDimitry Andric writer.write<uint16_t>(VI.getType().size()); 6705f757f3fSDimitry Andric OS.write(VI.getType().data(), VI.getType().size()); 6715f757f3fSDimitry Andric } 6725f757f3fSDimitry Andric 6735f757f3fSDimitry Andric /// Used to serialize the on-disk Objective-C property table. 6745f757f3fSDimitry Andric class ObjCPropertyTableInfo 6755f757f3fSDimitry Andric : public VersionedTableInfo<ObjCPropertyTableInfo, 6765f757f3fSDimitry Andric std::tuple<unsigned, unsigned, char>, 6775f757f3fSDimitry Andric ObjCPropertyInfo> { 6785f757f3fSDimitry Andric public: 6795f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { 6805f757f3fSDimitry Andric return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t); 6815f757f3fSDimitry Andric } 6825f757f3fSDimitry Andric 6835f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 6845f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 6855f757f3fSDimitry Andric writer.write<uint32_t>(std::get<0>(Key)); 6865f757f3fSDimitry Andric writer.write<uint32_t>(std::get<1>(Key)); 6875f757f3fSDimitry Andric writer.write<uint8_t>(std::get<2>(Key)); 6885f757f3fSDimitry Andric } 6895f757f3fSDimitry Andric 6905f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 6915f757f3fSDimitry Andric return static_cast<size_t>(llvm::hash_value(Key)); 6925f757f3fSDimitry Andric } 6935f757f3fSDimitry Andric 6945f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const ObjCPropertyInfo &OPI) { 6955f757f3fSDimitry Andric return getVariableInfoSize(OPI) + 1; 6965f757f3fSDimitry Andric } 6975f757f3fSDimitry Andric 6985f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const ObjCPropertyInfo &OPI) { 6995f757f3fSDimitry Andric emitVariableInfo(OS, OPI); 7005f757f3fSDimitry Andric 7015f757f3fSDimitry Andric uint8_t flags = 0; 7025f757f3fSDimitry Andric if (auto value = OPI.getSwiftImportAsAccessors()) { 7035f757f3fSDimitry Andric flags |= 1 << 0; 7045f757f3fSDimitry Andric flags |= value.value() << 1; 7055f757f3fSDimitry Andric } 7065f757f3fSDimitry Andric OS << flags; 7075f757f3fSDimitry Andric } 7085f757f3fSDimitry Andric }; 7095f757f3fSDimitry Andric } // namespace 7105f757f3fSDimitry Andric 7115f757f3fSDimitry Andric void APINotesWriter::Implementation::writeObjCPropertyBlock( 7125f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 7135f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, OBJC_PROPERTY_BLOCK_ID, 3); 7145f757f3fSDimitry Andric 7155f757f3fSDimitry Andric if (ObjCProperties.empty()) 7165f757f3fSDimitry Andric return; 7175f757f3fSDimitry Andric 7185f757f3fSDimitry Andric { 7195f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 7205f757f3fSDimitry Andric uint32_t Offset; 7215f757f3fSDimitry Andric { 7225f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo> Generator; 7235f757f3fSDimitry Andric for (auto &OP : ObjCProperties) 7245f757f3fSDimitry Andric Generator.insert(OP.first, OP.second); 7255f757f3fSDimitry Andric 7265f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 7275f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 7285f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 7295f757f3fSDimitry Andric llvm::endianness::little); 7305f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 7315f757f3fSDimitry Andric } 7325f757f3fSDimitry Andric 7335f757f3fSDimitry Andric objc_property_block::ObjCPropertyDataLayout ObjCPropertyData(Stream); 7345f757f3fSDimitry Andric ObjCPropertyData.emit(Scratch, Offset, HashTableBlob); 7355f757f3fSDimitry Andric } 7365f757f3fSDimitry Andric } 7375f757f3fSDimitry Andric 7385f757f3fSDimitry Andric namespace { 7395f757f3fSDimitry Andric unsigned getFunctionInfoSize(const FunctionInfo &); 7405f757f3fSDimitry Andric void emitFunctionInfo(llvm::raw_ostream &, const FunctionInfo &); 7415f757f3fSDimitry Andric 7425f757f3fSDimitry Andric /// Used to serialize the on-disk Objective-C method table. 7435f757f3fSDimitry Andric class ObjCMethodTableInfo 7445f757f3fSDimitry Andric : public VersionedTableInfo<ObjCMethodTableInfo, 7455f757f3fSDimitry Andric std::tuple<unsigned, unsigned, char>, 7465f757f3fSDimitry Andric ObjCMethodInfo> { 7475f757f3fSDimitry Andric public: 7485f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { 7495f757f3fSDimitry Andric return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t); 7505f757f3fSDimitry Andric } 7515f757f3fSDimitry Andric 7525f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 7535f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 7545f757f3fSDimitry Andric writer.write<uint32_t>(std::get<0>(Key)); 7555f757f3fSDimitry Andric writer.write<uint32_t>(std::get<1>(Key)); 7565f757f3fSDimitry Andric writer.write<uint8_t>(std::get<2>(Key)); 7575f757f3fSDimitry Andric } 7585f757f3fSDimitry Andric 7595f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref key) { 7605f757f3fSDimitry Andric return static_cast<size_t>(llvm::hash_value(key)); 7615f757f3fSDimitry Andric } 7625f757f3fSDimitry Andric 7635f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const ObjCMethodInfo &OMI) { 7645f757f3fSDimitry Andric return getFunctionInfoSize(OMI) + 1; 7655f757f3fSDimitry Andric } 7665f757f3fSDimitry Andric 7675f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const ObjCMethodInfo &OMI) { 7685f757f3fSDimitry Andric uint8_t flags = 0; 7695f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 7705f757f3fSDimitry Andric flags = (flags << 1) | OMI.DesignatedInit; 7715f757f3fSDimitry Andric flags = (flags << 1) | OMI.RequiredInit; 7725f757f3fSDimitry Andric writer.write<uint8_t>(flags); 7735f757f3fSDimitry Andric 7745f757f3fSDimitry Andric emitFunctionInfo(OS, OMI); 7755f757f3fSDimitry Andric } 7765f757f3fSDimitry Andric }; 777*0fca6ea1SDimitry Andric 778*0fca6ea1SDimitry Andric /// Used to serialize the on-disk C++ method table. 779*0fca6ea1SDimitry Andric class CXXMethodTableInfo 780*0fca6ea1SDimitry Andric : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey, 781*0fca6ea1SDimitry Andric CXXMethodInfo> { 782*0fca6ea1SDimitry Andric public: 783*0fca6ea1SDimitry Andric unsigned getKeyLength(key_type_ref) { 784*0fca6ea1SDimitry Andric return sizeof(uint32_t) + sizeof(uint32_t); 785*0fca6ea1SDimitry Andric } 786*0fca6ea1SDimitry Andric 787*0fca6ea1SDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 788*0fca6ea1SDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 789*0fca6ea1SDimitry Andric writer.write<uint32_t>(Key.parentContextID); 790*0fca6ea1SDimitry Andric writer.write<uint32_t>(Key.nameID); 791*0fca6ea1SDimitry Andric } 792*0fca6ea1SDimitry Andric 793*0fca6ea1SDimitry Andric hash_value_type ComputeHash(key_type_ref key) { 794*0fca6ea1SDimitry Andric return static_cast<size_t>(key.hashValue()); 795*0fca6ea1SDimitry Andric } 796*0fca6ea1SDimitry Andric 797*0fca6ea1SDimitry Andric unsigned getUnversionedInfoSize(const CXXMethodInfo &OMI) { 798*0fca6ea1SDimitry Andric return getFunctionInfoSize(OMI); 799*0fca6ea1SDimitry Andric } 800*0fca6ea1SDimitry Andric 801*0fca6ea1SDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const CXXMethodInfo &OMI) { 802*0fca6ea1SDimitry Andric emitFunctionInfo(OS, OMI); 803*0fca6ea1SDimitry Andric } 804*0fca6ea1SDimitry Andric }; 8055f757f3fSDimitry Andric } // namespace 8065f757f3fSDimitry Andric 8075f757f3fSDimitry Andric void APINotesWriter::Implementation::writeObjCMethodBlock( 8085f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 8095f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, OBJC_METHOD_BLOCK_ID, 3); 8105f757f3fSDimitry Andric 8115f757f3fSDimitry Andric if (ObjCMethods.empty()) 8125f757f3fSDimitry Andric return; 8135f757f3fSDimitry Andric 8145f757f3fSDimitry Andric { 8155f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 8165f757f3fSDimitry Andric uint32_t Offset; 8175f757f3fSDimitry Andric { 8185f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo> Generator; 8195f757f3fSDimitry Andric for (auto &OM : ObjCMethods) 8205f757f3fSDimitry Andric Generator.insert(OM.first, OM.second); 8215f757f3fSDimitry Andric 8225f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 8235f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 8245f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 8255f757f3fSDimitry Andric llvm::endianness::little); 8265f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 8275f757f3fSDimitry Andric } 8285f757f3fSDimitry Andric 8295f757f3fSDimitry Andric objc_method_block::ObjCMethodDataLayout ObjCMethodData(Stream); 8305f757f3fSDimitry Andric ObjCMethodData.emit(Scratch, Offset, HashTableBlob); 8315f757f3fSDimitry Andric } 8325f757f3fSDimitry Andric } 8335f757f3fSDimitry Andric 834*0fca6ea1SDimitry Andric void APINotesWriter::Implementation::writeCXXMethodBlock( 835*0fca6ea1SDimitry Andric llvm::BitstreamWriter &Stream) { 836*0fca6ea1SDimitry Andric llvm::BCBlockRAII Scope(Stream, CXX_METHOD_BLOCK_ID, 3); 837*0fca6ea1SDimitry Andric 838*0fca6ea1SDimitry Andric if (CXXMethods.empty()) 839*0fca6ea1SDimitry Andric return; 840*0fca6ea1SDimitry Andric 841*0fca6ea1SDimitry Andric { 842*0fca6ea1SDimitry Andric llvm::SmallString<4096> HashTableBlob; 843*0fca6ea1SDimitry Andric uint32_t Offset; 844*0fca6ea1SDimitry Andric { 845*0fca6ea1SDimitry Andric llvm::OnDiskChainedHashTableGenerator<CXXMethodTableInfo> Generator; 846*0fca6ea1SDimitry Andric for (auto &MD : CXXMethods) 847*0fca6ea1SDimitry Andric Generator.insert(MD.first, MD.second); 848*0fca6ea1SDimitry Andric 849*0fca6ea1SDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 850*0fca6ea1SDimitry Andric // Make sure that no bucket is at offset 0 851*0fca6ea1SDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 852*0fca6ea1SDimitry Andric llvm::endianness::little); 853*0fca6ea1SDimitry Andric Offset = Generator.Emit(BlobStream); 854*0fca6ea1SDimitry Andric } 855*0fca6ea1SDimitry Andric 856*0fca6ea1SDimitry Andric cxx_method_block::CXXMethodDataLayout CXXMethodData(Stream); 857*0fca6ea1SDimitry Andric CXXMethodData.emit(Scratch, Offset, HashTableBlob); 858*0fca6ea1SDimitry Andric } 859*0fca6ea1SDimitry Andric } 860*0fca6ea1SDimitry Andric 8615f757f3fSDimitry Andric namespace { 8625f757f3fSDimitry Andric /// Used to serialize the on-disk Objective-C selector table. 8635f757f3fSDimitry Andric class ObjCSelectorTableInfo { 8645f757f3fSDimitry Andric public: 8655f757f3fSDimitry Andric using key_type = StoredObjCSelector; 8665f757f3fSDimitry Andric using key_type_ref = const key_type &; 8675f757f3fSDimitry Andric using data_type = SelectorID; 8685f757f3fSDimitry Andric using data_type_ref = data_type; 8695f757f3fSDimitry Andric using hash_value_type = unsigned; 8705f757f3fSDimitry Andric using offset_type = unsigned; 8715f757f3fSDimitry Andric 8725f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 8735f757f3fSDimitry Andric return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key); 8745f757f3fSDimitry Andric } 8755f757f3fSDimitry Andric 8765f757f3fSDimitry Andric std::pair<unsigned, unsigned> 8775f757f3fSDimitry Andric EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) { 8785f757f3fSDimitry Andric uint32_t KeyLength = 8795f757f3fSDimitry Andric sizeof(uint16_t) + sizeof(uint32_t) * Key.Identifiers.size(); 8805f757f3fSDimitry Andric uint32_t DataLength = sizeof(uint32_t); 8815f757f3fSDimitry Andric 8825f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 8835f757f3fSDimitry Andric writer.write<uint16_t>(KeyLength); 8845f757f3fSDimitry Andric writer.write<uint16_t>(DataLength); 8855f757f3fSDimitry Andric return {KeyLength, DataLength}; 8865f757f3fSDimitry Andric } 8875f757f3fSDimitry Andric 8885f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 8895f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 8905f757f3fSDimitry Andric writer.write<uint16_t>(Key.NumArgs); 8915f757f3fSDimitry Andric for (auto Identifier : Key.Identifiers) 8925f757f3fSDimitry Andric writer.write<uint32_t>(Identifier); 8935f757f3fSDimitry Andric } 8945f757f3fSDimitry Andric 8955f757f3fSDimitry Andric void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) { 8965f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 8975f757f3fSDimitry Andric writer.write<uint32_t>(Data); 8985f757f3fSDimitry Andric } 8995f757f3fSDimitry Andric }; 9005f757f3fSDimitry Andric } // namespace 9015f757f3fSDimitry Andric 9025f757f3fSDimitry Andric void APINotesWriter::Implementation::writeObjCSelectorBlock( 9035f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 9045f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, OBJC_SELECTOR_BLOCK_ID, 3); 9055f757f3fSDimitry Andric 9065f757f3fSDimitry Andric if (SelectorIDs.empty()) 9075f757f3fSDimitry Andric return; 9085f757f3fSDimitry Andric 9095f757f3fSDimitry Andric { 9105f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 9115f757f3fSDimitry Andric uint32_t Offset; 9125f757f3fSDimitry Andric { 9135f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo> Generator; 9145f757f3fSDimitry Andric for (auto &S : SelectorIDs) 9155f757f3fSDimitry Andric Generator.insert(S.first, S.second); 9165f757f3fSDimitry Andric 9175f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 9185f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 9195f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 9205f757f3fSDimitry Andric llvm::endianness::little); 9215f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 9225f757f3fSDimitry Andric } 9235f757f3fSDimitry Andric 9245f757f3fSDimitry Andric objc_selector_block::ObjCSelectorDataLayout ObjCSelectorData(Stream); 9255f757f3fSDimitry Andric ObjCSelectorData.emit(Scratch, Offset, HashTableBlob); 9265f757f3fSDimitry Andric } 9275f757f3fSDimitry Andric } 9285f757f3fSDimitry Andric 9295f757f3fSDimitry Andric namespace { 9305f757f3fSDimitry Andric /// Used to serialize the on-disk global variable table. 9315f757f3fSDimitry Andric class GlobalVariableTableInfo 932*0fca6ea1SDimitry Andric : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey, 9335f757f3fSDimitry Andric GlobalVariableInfo> { 9345f757f3fSDimitry Andric public: 9355f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { 936*0fca6ea1SDimitry Andric return sizeof(uint32_t) + sizeof(uint32_t); 9375f757f3fSDimitry Andric } 9385f757f3fSDimitry Andric 9395f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 9405f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 9415f757f3fSDimitry Andric writer.write<uint32_t>(Key.parentContextID); 942*0fca6ea1SDimitry Andric writer.write<uint32_t>(Key.nameID); 9435f757f3fSDimitry Andric } 9445f757f3fSDimitry Andric 9455f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 9465f757f3fSDimitry Andric return static_cast<size_t>(Key.hashValue()); 9475f757f3fSDimitry Andric } 9485f757f3fSDimitry Andric 9495f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const GlobalVariableInfo &GVI) { 9505f757f3fSDimitry Andric return getVariableInfoSize(GVI); 9515f757f3fSDimitry Andric } 9525f757f3fSDimitry Andric 9535f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const GlobalVariableInfo &GVI) { 9545f757f3fSDimitry Andric emitVariableInfo(OS, GVI); 9555f757f3fSDimitry Andric } 9565f757f3fSDimitry Andric }; 9575f757f3fSDimitry Andric } // namespace 9585f757f3fSDimitry Andric 9595f757f3fSDimitry Andric void APINotesWriter::Implementation::writeGlobalVariableBlock( 9605f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 9615f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, GLOBAL_VARIABLE_BLOCK_ID, 3); 9625f757f3fSDimitry Andric 9635f757f3fSDimitry Andric if (GlobalVariables.empty()) 9645f757f3fSDimitry Andric return; 9655f757f3fSDimitry Andric 9665f757f3fSDimitry Andric { 9675f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 9685f757f3fSDimitry Andric uint32_t Offset; 9695f757f3fSDimitry Andric { 9705f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo> Generator; 9715f757f3fSDimitry Andric for (auto &GV : GlobalVariables) 9725f757f3fSDimitry Andric Generator.insert(GV.first, GV.second); 9735f757f3fSDimitry Andric 9745f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 9755f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 9765f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 9775f757f3fSDimitry Andric llvm::endianness::little); 9785f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 9795f757f3fSDimitry Andric } 9805f757f3fSDimitry Andric 9815f757f3fSDimitry Andric global_variable_block::GlobalVariableDataLayout GlobalVariableData(Stream); 9825f757f3fSDimitry Andric GlobalVariableData.emit(Scratch, Offset, HashTableBlob); 9835f757f3fSDimitry Andric } 9845f757f3fSDimitry Andric } 9855f757f3fSDimitry Andric 9865f757f3fSDimitry Andric namespace { 9875f757f3fSDimitry Andric unsigned getParamInfoSize(const ParamInfo &PI) { 9885f757f3fSDimitry Andric return getVariableInfoSize(PI) + 1; 9895f757f3fSDimitry Andric } 9905f757f3fSDimitry Andric 9915f757f3fSDimitry Andric void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) { 9925f757f3fSDimitry Andric emitVariableInfo(OS, PI); 9935f757f3fSDimitry Andric 9945f757f3fSDimitry Andric uint8_t flags = 0; 9955f757f3fSDimitry Andric if (auto noescape = PI.isNoEscape()) { 9965f757f3fSDimitry Andric flags |= 0x01; 9975f757f3fSDimitry Andric if (*noescape) 9985f757f3fSDimitry Andric flags |= 0x02; 9995f757f3fSDimitry Andric } 10005f757f3fSDimitry Andric flags <<= 3; 10015f757f3fSDimitry Andric if (auto RCC = PI.getRetainCountConvention()) 10025f757f3fSDimitry Andric flags |= static_cast<uint8_t>(RCC.value()) + 1; 10035f757f3fSDimitry Andric 10045f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 10055f757f3fSDimitry Andric writer.write<uint8_t>(flags); 10065f757f3fSDimitry Andric } 10075f757f3fSDimitry Andric 10085f757f3fSDimitry Andric /// Retrieve the serialized size of the given FunctionInfo, for use in on-disk 10095f757f3fSDimitry Andric /// hash tables. 10105f757f3fSDimitry Andric unsigned getFunctionInfoSize(const FunctionInfo &FI) { 10115f757f3fSDimitry Andric unsigned size = getCommonEntityInfoSize(FI) + 2 + sizeof(uint64_t); 10125f757f3fSDimitry Andric size += sizeof(uint16_t); 10135f757f3fSDimitry Andric for (const auto &P : FI.Params) 10145f757f3fSDimitry Andric size += getParamInfoSize(P); 10155f757f3fSDimitry Andric size += sizeof(uint16_t) + FI.ResultType.size(); 10165f757f3fSDimitry Andric return size; 10175f757f3fSDimitry Andric } 10185f757f3fSDimitry Andric 10195f757f3fSDimitry Andric /// Emit a serialized representation of the function information. 10205f757f3fSDimitry Andric void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) { 10215f757f3fSDimitry Andric emitCommonEntityInfo(OS, FI); 10225f757f3fSDimitry Andric 10235f757f3fSDimitry Andric uint8_t flags = 0; 10245f757f3fSDimitry Andric flags |= FI.NullabilityAudited; 10255f757f3fSDimitry Andric flags <<= 3; 10265f757f3fSDimitry Andric if (auto RCC = FI.getRetainCountConvention()) 10275f757f3fSDimitry Andric flags |= static_cast<uint8_t>(RCC.value()) + 1; 10285f757f3fSDimitry Andric 10295f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 10305f757f3fSDimitry Andric 10315f757f3fSDimitry Andric writer.write<uint8_t>(flags); 10325f757f3fSDimitry Andric writer.write<uint8_t>(FI.NumAdjustedNullable); 10335f757f3fSDimitry Andric writer.write<uint64_t>(FI.NullabilityPayload); 10345f757f3fSDimitry Andric 10355f757f3fSDimitry Andric writer.write<uint16_t>(FI.Params.size()); 10365f757f3fSDimitry Andric for (const auto &PI : FI.Params) 10375f757f3fSDimitry Andric emitParamInfo(OS, PI); 10385f757f3fSDimitry Andric 10395f757f3fSDimitry Andric writer.write<uint16_t>(FI.ResultType.size()); 10405f757f3fSDimitry Andric writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()}); 10415f757f3fSDimitry Andric } 10425f757f3fSDimitry Andric 10435f757f3fSDimitry Andric /// Used to serialize the on-disk global function table. 10445f757f3fSDimitry Andric class GlobalFunctionTableInfo 1045*0fca6ea1SDimitry Andric : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey, 10465f757f3fSDimitry Andric GlobalFunctionInfo> { 10475f757f3fSDimitry Andric public: 10485f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { 1049*0fca6ea1SDimitry Andric return sizeof(uint32_t) + sizeof(uint32_t); 10505f757f3fSDimitry Andric } 10515f757f3fSDimitry Andric 10525f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 10535f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 10545f757f3fSDimitry Andric writer.write<uint32_t>(Key.parentContextID); 1055*0fca6ea1SDimitry Andric writer.write<uint32_t>(Key.nameID); 10565f757f3fSDimitry Andric } 10575f757f3fSDimitry Andric 10585f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 10595f757f3fSDimitry Andric return static_cast<size_t>(Key.hashValue()); 10605f757f3fSDimitry Andric } 10615f757f3fSDimitry Andric 10625f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const GlobalFunctionInfo &GFI) { 10635f757f3fSDimitry Andric return getFunctionInfoSize(GFI); 10645f757f3fSDimitry Andric } 10655f757f3fSDimitry Andric 10665f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const GlobalFunctionInfo &GFI) { 10675f757f3fSDimitry Andric emitFunctionInfo(OS, GFI); 10685f757f3fSDimitry Andric } 10695f757f3fSDimitry Andric }; 10705f757f3fSDimitry Andric } // namespace 10715f757f3fSDimitry Andric 10725f757f3fSDimitry Andric void APINotesWriter::Implementation::writeGlobalFunctionBlock( 10735f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 10745f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, GLOBAL_FUNCTION_BLOCK_ID, 3); 10755f757f3fSDimitry Andric 10765f757f3fSDimitry Andric if (GlobalFunctions.empty()) 10775f757f3fSDimitry Andric return; 10785f757f3fSDimitry Andric 10795f757f3fSDimitry Andric { 10805f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 10815f757f3fSDimitry Andric uint32_t Offset; 10825f757f3fSDimitry Andric { 10835f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo> Generator; 10845f757f3fSDimitry Andric for (auto &F : GlobalFunctions) 10855f757f3fSDimitry Andric Generator.insert(F.first, F.second); 10865f757f3fSDimitry Andric 10875f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 10885f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 10895f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 10905f757f3fSDimitry Andric llvm::endianness::little); 10915f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 10925f757f3fSDimitry Andric } 10935f757f3fSDimitry Andric 10945f757f3fSDimitry Andric global_function_block::GlobalFunctionDataLayout GlobalFunctionData(Stream); 10955f757f3fSDimitry Andric GlobalFunctionData.emit(Scratch, Offset, HashTableBlob); 10965f757f3fSDimitry Andric } 10975f757f3fSDimitry Andric } 10985f757f3fSDimitry Andric 10995f757f3fSDimitry Andric namespace { 11005f757f3fSDimitry Andric /// Used to serialize the on-disk global enum constant. 11015f757f3fSDimitry Andric class EnumConstantTableInfo 11025f757f3fSDimitry Andric : public VersionedTableInfo<EnumConstantTableInfo, unsigned, 11035f757f3fSDimitry Andric EnumConstantInfo> { 11045f757f3fSDimitry Andric public: 11055f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); } 11065f757f3fSDimitry Andric 11075f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 11085f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 11095f757f3fSDimitry Andric writer.write<uint32_t>(Key); 11105f757f3fSDimitry Andric } 11115f757f3fSDimitry Andric 11125f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 11135f757f3fSDimitry Andric return static_cast<size_t>(llvm::hash_value(Key)); 11145f757f3fSDimitry Andric } 11155f757f3fSDimitry Andric 11165f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const EnumConstantInfo &ECI) { 11175f757f3fSDimitry Andric return getCommonEntityInfoSize(ECI); 11185f757f3fSDimitry Andric } 11195f757f3fSDimitry Andric 11205f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const EnumConstantInfo &ECI) { 11215f757f3fSDimitry Andric emitCommonEntityInfo(OS, ECI); 11225f757f3fSDimitry Andric } 11235f757f3fSDimitry Andric }; 11245f757f3fSDimitry Andric } // namespace 11255f757f3fSDimitry Andric 11265f757f3fSDimitry Andric void APINotesWriter::Implementation::writeEnumConstantBlock( 11275f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 11285f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, ENUM_CONSTANT_BLOCK_ID, 3); 11295f757f3fSDimitry Andric 11305f757f3fSDimitry Andric if (EnumConstants.empty()) 11315f757f3fSDimitry Andric return; 11325f757f3fSDimitry Andric 11335f757f3fSDimitry Andric { 11345f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 11355f757f3fSDimitry Andric uint32_t Offset; 11365f757f3fSDimitry Andric { 11375f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo> Generator; 11385f757f3fSDimitry Andric for (auto &EC : EnumConstants) 11395f757f3fSDimitry Andric Generator.insert(EC.first, EC.second); 11405f757f3fSDimitry Andric 11415f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 11425f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 11435f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 11445f757f3fSDimitry Andric llvm::endianness::little); 11455f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 11465f757f3fSDimitry Andric } 11475f757f3fSDimitry Andric 11485f757f3fSDimitry Andric enum_constant_block::EnumConstantDataLayout EnumConstantData(Stream); 11495f757f3fSDimitry Andric EnumConstantData.emit(Scratch, Offset, HashTableBlob); 11505f757f3fSDimitry Andric } 11515f757f3fSDimitry Andric } 11525f757f3fSDimitry Andric 11535f757f3fSDimitry Andric namespace { 11545f757f3fSDimitry Andric template <typename Derived, typename UnversionedDataType> 11555f757f3fSDimitry Andric class CommonTypeTableInfo 1156*0fca6ea1SDimitry Andric : public VersionedTableInfo<Derived, SingleDeclTableKey, 1157*0fca6ea1SDimitry Andric UnversionedDataType> { 11585f757f3fSDimitry Andric public: 11595f757f3fSDimitry Andric using key_type_ref = typename CommonTypeTableInfo::key_type_ref; 11605f757f3fSDimitry Andric using hash_value_type = typename CommonTypeTableInfo::hash_value_type; 11615f757f3fSDimitry Andric 11625f757f3fSDimitry Andric unsigned getKeyLength(key_type_ref) { 1163*0fca6ea1SDimitry Andric return sizeof(uint32_t) + sizeof(IdentifierID); 11645f757f3fSDimitry Andric } 11655f757f3fSDimitry Andric 11665f757f3fSDimitry Andric void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { 11675f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 11685f757f3fSDimitry Andric writer.write<uint32_t>(Key.parentContextID); 1169*0fca6ea1SDimitry Andric writer.write<IdentifierID>(Key.nameID); 11705f757f3fSDimitry Andric } 11715f757f3fSDimitry Andric 11725f757f3fSDimitry Andric hash_value_type ComputeHash(key_type_ref Key) { 11735f757f3fSDimitry Andric return static_cast<size_t>(Key.hashValue()); 11745f757f3fSDimitry Andric } 11755f757f3fSDimitry Andric 11765f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const UnversionedDataType &UDT) { 11775f757f3fSDimitry Andric return getCommonTypeInfoSize(UDT); 11785f757f3fSDimitry Andric } 11795f757f3fSDimitry Andric 11805f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const UnversionedDataType &UDT) { 11815f757f3fSDimitry Andric emitCommonTypeInfo(OS, UDT); 11825f757f3fSDimitry Andric } 11835f757f3fSDimitry Andric }; 11845f757f3fSDimitry Andric 11855f757f3fSDimitry Andric /// Used to serialize the on-disk tag table. 11865f757f3fSDimitry Andric class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> { 11875f757f3fSDimitry Andric public: 11885f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const TagInfo &TI) { 11895f757f3fSDimitry Andric return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 11905f757f3fSDimitry Andric 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 11915f757f3fSDimitry Andric 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 1192*0fca6ea1SDimitry Andric 2 + getCommonTypeInfoSize(TI); 11935f757f3fSDimitry Andric } 11945f757f3fSDimitry Andric 11955f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) { 11965f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 11975f757f3fSDimitry Andric 11985f757f3fSDimitry Andric uint8_t Flags = 0; 11995f757f3fSDimitry Andric if (auto extensibility = TI.EnumExtensibility) { 12005f757f3fSDimitry Andric Flags |= static_cast<uint8_t>(extensibility.value()) + 1; 12015f757f3fSDimitry Andric assert((Flags < (1 << 2)) && "must fit in two bits"); 12025f757f3fSDimitry Andric } 12035f757f3fSDimitry Andric 12045f757f3fSDimitry Andric Flags <<= 2; 12055f757f3fSDimitry Andric if (auto value = TI.isFlagEnum()) 12065f757f3fSDimitry Andric Flags |= (value.value() << 1 | 1 << 0); 12075f757f3fSDimitry Andric 12085f757f3fSDimitry Andric writer.write<uint8_t>(Flags); 12095f757f3fSDimitry Andric 1210*0fca6ea1SDimitry Andric if (auto Copyable = TI.isSwiftCopyable()) 1211*0fca6ea1SDimitry Andric writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable); 1212*0fca6ea1SDimitry Andric else 1213*0fca6ea1SDimitry Andric writer.write<uint8_t>(0); 1214*0fca6ea1SDimitry Andric 12155f757f3fSDimitry Andric if (auto ImportAs = TI.SwiftImportAs) { 12165f757f3fSDimitry Andric writer.write<uint16_t>(ImportAs->size() + 1); 12175f757f3fSDimitry Andric OS.write(ImportAs->c_str(), ImportAs->size()); 12185f757f3fSDimitry Andric } else { 12195f757f3fSDimitry Andric writer.write<uint16_t>(0); 12205f757f3fSDimitry Andric } 12215f757f3fSDimitry Andric if (auto RetainOp = TI.SwiftRetainOp) { 12225f757f3fSDimitry Andric writer.write<uint16_t>(RetainOp->size() + 1); 12235f757f3fSDimitry Andric OS.write(RetainOp->c_str(), RetainOp->size()); 12245f757f3fSDimitry Andric } else { 12255f757f3fSDimitry Andric writer.write<uint16_t>(0); 12265f757f3fSDimitry Andric } 12275f757f3fSDimitry Andric if (auto ReleaseOp = TI.SwiftReleaseOp) { 12285f757f3fSDimitry Andric writer.write<uint16_t>(ReleaseOp->size() + 1); 12295f757f3fSDimitry Andric OS.write(ReleaseOp->c_str(), ReleaseOp->size()); 12305f757f3fSDimitry Andric } else { 12315f757f3fSDimitry Andric writer.write<uint16_t>(0); 12325f757f3fSDimitry Andric } 12335f757f3fSDimitry Andric 12345f757f3fSDimitry Andric emitCommonTypeInfo(OS, TI); 12355f757f3fSDimitry Andric } 12365f757f3fSDimitry Andric }; 12375f757f3fSDimitry Andric } // namespace 12385f757f3fSDimitry Andric 12395f757f3fSDimitry Andric void APINotesWriter::Implementation::writeTagBlock( 12405f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 12415f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, TAG_BLOCK_ID, 3); 12425f757f3fSDimitry Andric 12435f757f3fSDimitry Andric if (Tags.empty()) 12445f757f3fSDimitry Andric return; 12455f757f3fSDimitry Andric 12465f757f3fSDimitry Andric { 12475f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 12485f757f3fSDimitry Andric uint32_t Offset; 12495f757f3fSDimitry Andric { 12505f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<TagTableInfo> Generator; 12515f757f3fSDimitry Andric for (auto &T : Tags) 12525f757f3fSDimitry Andric Generator.insert(T.first, T.second); 12535f757f3fSDimitry Andric 12545f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 12555f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 12565f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 12575f757f3fSDimitry Andric llvm::endianness::little); 12585f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 12595f757f3fSDimitry Andric } 12605f757f3fSDimitry Andric 12615f757f3fSDimitry Andric tag_block::TagDataLayout TagData(Stream); 12625f757f3fSDimitry Andric TagData.emit(Scratch, Offset, HashTableBlob); 12635f757f3fSDimitry Andric } 12645f757f3fSDimitry Andric } 12655f757f3fSDimitry Andric 12665f757f3fSDimitry Andric namespace { 12675f757f3fSDimitry Andric /// Used to serialize the on-disk typedef table. 12685f757f3fSDimitry Andric class TypedefTableInfo 12695f757f3fSDimitry Andric : public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> { 12705f757f3fSDimitry Andric public: 12715f757f3fSDimitry Andric unsigned getUnversionedInfoSize(const TypedefInfo &TI) { 12725f757f3fSDimitry Andric return 1 + getCommonTypeInfoSize(TI); 12735f757f3fSDimitry Andric } 12745f757f3fSDimitry Andric 12755f757f3fSDimitry Andric void emitUnversionedInfo(raw_ostream &OS, const TypedefInfo &TI) { 12765f757f3fSDimitry Andric llvm::support::endian::Writer writer(OS, llvm::endianness::little); 12775f757f3fSDimitry Andric 12785f757f3fSDimitry Andric uint8_t Flags = 0; 12795f757f3fSDimitry Andric if (auto swiftWrapper = TI.SwiftWrapper) 12805f757f3fSDimitry Andric Flags |= static_cast<uint8_t>(*swiftWrapper) + 1; 12815f757f3fSDimitry Andric 12825f757f3fSDimitry Andric writer.write<uint8_t>(Flags); 12835f757f3fSDimitry Andric 12845f757f3fSDimitry Andric emitCommonTypeInfo(OS, TI); 12855f757f3fSDimitry Andric } 12865f757f3fSDimitry Andric }; 12875f757f3fSDimitry Andric } // namespace 12885f757f3fSDimitry Andric 12895f757f3fSDimitry Andric void APINotesWriter::Implementation::writeTypedefBlock( 12905f757f3fSDimitry Andric llvm::BitstreamWriter &Stream) { 12915f757f3fSDimitry Andric llvm::BCBlockRAII Scope(Stream, TYPEDEF_BLOCK_ID, 3); 12925f757f3fSDimitry Andric 12935f757f3fSDimitry Andric if (Typedefs.empty()) 12945f757f3fSDimitry Andric return; 12955f757f3fSDimitry Andric 12965f757f3fSDimitry Andric { 12975f757f3fSDimitry Andric llvm::SmallString<4096> HashTableBlob; 12985f757f3fSDimitry Andric uint32_t Offset; 12995f757f3fSDimitry Andric { 13005f757f3fSDimitry Andric llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo> Generator; 13015f757f3fSDimitry Andric for (auto &T : Typedefs) 13025f757f3fSDimitry Andric Generator.insert(T.first, T.second); 13035f757f3fSDimitry Andric 13045f757f3fSDimitry Andric llvm::raw_svector_ostream BlobStream(HashTableBlob); 13055f757f3fSDimitry Andric // Make sure that no bucket is at offset 0 13065f757f3fSDimitry Andric llvm::support::endian::write<uint32_t>(BlobStream, 0, 13075f757f3fSDimitry Andric llvm::endianness::little); 13085f757f3fSDimitry Andric Offset = Generator.Emit(BlobStream); 13095f757f3fSDimitry Andric } 13105f757f3fSDimitry Andric 13115f757f3fSDimitry Andric typedef_block::TypedefDataLayout TypedefData(Stream); 13125f757f3fSDimitry Andric TypedefData.emit(Scratch, Offset, HashTableBlob); 13135f757f3fSDimitry Andric } 13145f757f3fSDimitry Andric } 13155f757f3fSDimitry Andric 13165f757f3fSDimitry Andric // APINotesWriter 13175f757f3fSDimitry Andric 13185f757f3fSDimitry Andric APINotesWriter::APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF) 13195f757f3fSDimitry Andric : Implementation(new class Implementation(ModuleName, SF)) {} 13205f757f3fSDimitry Andric 13215f757f3fSDimitry Andric APINotesWriter::~APINotesWriter() = default; 13225f757f3fSDimitry Andric 13235f757f3fSDimitry Andric void APINotesWriter::writeToStream(llvm::raw_ostream &OS) { 13245f757f3fSDimitry Andric Implementation->writeToStream(OS); 13255f757f3fSDimitry Andric } 13265f757f3fSDimitry Andric 1327*0fca6ea1SDimitry Andric ContextID APINotesWriter::addContext(std::optional<ContextID> ParentCtxID, 1328*0fca6ea1SDimitry Andric llvm::StringRef Name, ContextKind Kind, 1329*0fca6ea1SDimitry Andric const ContextInfo &Info, 1330*0fca6ea1SDimitry Andric llvm::VersionTuple SwiftVersion) { 13315f757f3fSDimitry Andric IdentifierID NameID = Implementation->getIdentifier(Name); 13325f757f3fSDimitry Andric 13335f757f3fSDimitry Andric uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1; 13345f757f3fSDimitry Andric ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID); 1335*0fca6ea1SDimitry Andric auto Known = Implementation->Contexts.find(Key); 1336*0fca6ea1SDimitry Andric if (Known == Implementation->Contexts.end()) { 1337*0fca6ea1SDimitry Andric unsigned NextID = Implementation->Contexts.size() + 1; 13385f757f3fSDimitry Andric 1339*0fca6ea1SDimitry Andric Implementation::VersionedSmallVector<ContextInfo> EmptyVersionedInfo; 1340*0fca6ea1SDimitry Andric Known = Implementation->Contexts 13415f757f3fSDimitry Andric .insert(std::make_pair( 13425f757f3fSDimitry Andric Key, std::make_pair(NextID, EmptyVersionedInfo))) 13435f757f3fSDimitry Andric .first; 13445f757f3fSDimitry Andric 1345*0fca6ea1SDimitry Andric Implementation->ContextNames[NextID] = NameID; 13465f757f3fSDimitry Andric Implementation->ParentContexts[NextID] = RawParentCtxID; 13475f757f3fSDimitry Andric } 13485f757f3fSDimitry Andric 13495f757f3fSDimitry Andric // Add this version information. 13505f757f3fSDimitry Andric auto &VersionedVec = Known->second.second; 13515f757f3fSDimitry Andric bool Found = false; 13525f757f3fSDimitry Andric for (auto &Versioned : VersionedVec) { 13535f757f3fSDimitry Andric if (Versioned.first == SwiftVersion) { 13545f757f3fSDimitry Andric Versioned.second |= Info; 13555f757f3fSDimitry Andric Found = true; 13565f757f3fSDimitry Andric break; 13575f757f3fSDimitry Andric } 13585f757f3fSDimitry Andric } 13595f757f3fSDimitry Andric 13605f757f3fSDimitry Andric if (!Found) 13615f757f3fSDimitry Andric VersionedVec.push_back({SwiftVersion, Info}); 13625f757f3fSDimitry Andric 13635f757f3fSDimitry Andric return ContextID(Known->second.first); 13645f757f3fSDimitry Andric } 13655f757f3fSDimitry Andric 13665f757f3fSDimitry Andric void APINotesWriter::addObjCProperty(ContextID CtxID, StringRef Name, 13675f757f3fSDimitry Andric bool IsInstanceProperty, 13685f757f3fSDimitry Andric const ObjCPropertyInfo &Info, 13695f757f3fSDimitry Andric VersionTuple SwiftVersion) { 13705f757f3fSDimitry Andric IdentifierID NameID = Implementation->getIdentifier(Name); 13715f757f3fSDimitry Andric Implementation 13725f757f3fSDimitry Andric ->ObjCProperties[std::make_tuple(CtxID.Value, NameID, IsInstanceProperty)] 13735f757f3fSDimitry Andric .push_back({SwiftVersion, Info}); 13745f757f3fSDimitry Andric } 13755f757f3fSDimitry Andric 13765f757f3fSDimitry Andric void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, 13775f757f3fSDimitry Andric bool IsInstanceMethod, 13785f757f3fSDimitry Andric const ObjCMethodInfo &Info, 13795f757f3fSDimitry Andric VersionTuple SwiftVersion) { 13805f757f3fSDimitry Andric SelectorID SelID = Implementation->getSelector(Selector); 13815f757f3fSDimitry Andric auto Key = std::tuple<unsigned, unsigned, char>{CtxID.Value, SelID, 13825f757f3fSDimitry Andric IsInstanceMethod}; 13835f757f3fSDimitry Andric Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info}); 13845f757f3fSDimitry Andric 13855f757f3fSDimitry Andric // If this method is a designated initializer, update the class to note that 13865f757f3fSDimitry Andric // it has designated initializers. 13875f757f3fSDimitry Andric if (Info.DesignatedInit) { 13885f757f3fSDimitry Andric assert(Implementation->ParentContexts.contains(CtxID.Value)); 13895f757f3fSDimitry Andric uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value]; 13905f757f3fSDimitry Andric ContextTableKey CtxKey(ParentCtxID, 13915f757f3fSDimitry Andric static_cast<uint8_t>(ContextKind::ObjCClass), 1392*0fca6ea1SDimitry Andric Implementation->ContextNames[CtxID.Value]); 1393*0fca6ea1SDimitry Andric assert(Implementation->Contexts.contains(CtxKey)); 1394*0fca6ea1SDimitry Andric auto &VersionedVec = Implementation->Contexts[CtxKey].second; 13955f757f3fSDimitry Andric bool Found = false; 13965f757f3fSDimitry Andric for (auto &Versioned : VersionedVec) { 13975f757f3fSDimitry Andric if (Versioned.first == SwiftVersion) { 13985f757f3fSDimitry Andric Versioned.second.setHasDesignatedInits(true); 13995f757f3fSDimitry Andric Found = true; 14005f757f3fSDimitry Andric break; 14015f757f3fSDimitry Andric } 14025f757f3fSDimitry Andric } 14035f757f3fSDimitry Andric 14045f757f3fSDimitry Andric if (!Found) { 1405*0fca6ea1SDimitry Andric VersionedVec.push_back({SwiftVersion, ContextInfo()}); 14065f757f3fSDimitry Andric VersionedVec.back().second.setHasDesignatedInits(true); 14075f757f3fSDimitry Andric } 14085f757f3fSDimitry Andric } 14095f757f3fSDimitry Andric } 14105f757f3fSDimitry Andric 1411*0fca6ea1SDimitry Andric void APINotesWriter::addCXXMethod(ContextID CtxID, llvm::StringRef Name, 1412*0fca6ea1SDimitry Andric const CXXMethodInfo &Info, 1413*0fca6ea1SDimitry Andric VersionTuple SwiftVersion) { 1414*0fca6ea1SDimitry Andric IdentifierID NameID = Implementation->getIdentifier(Name); 1415*0fca6ea1SDimitry Andric SingleDeclTableKey Key(CtxID.Value, NameID); 1416*0fca6ea1SDimitry Andric Implementation->CXXMethods[Key].push_back({SwiftVersion, Info}); 1417*0fca6ea1SDimitry Andric } 1418*0fca6ea1SDimitry Andric 14195f757f3fSDimitry Andric void APINotesWriter::addGlobalVariable(std::optional<Context> Ctx, 14205f757f3fSDimitry Andric llvm::StringRef Name, 14215f757f3fSDimitry Andric const GlobalVariableInfo &Info, 14225f757f3fSDimitry Andric VersionTuple SwiftVersion) { 14235f757f3fSDimitry Andric IdentifierID VariableID = Implementation->getIdentifier(Name); 1424*0fca6ea1SDimitry Andric SingleDeclTableKey Key(Ctx, VariableID); 14255f757f3fSDimitry Andric Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info}); 14265f757f3fSDimitry Andric } 14275f757f3fSDimitry Andric 14285f757f3fSDimitry Andric void APINotesWriter::addGlobalFunction(std::optional<Context> Ctx, 14295f757f3fSDimitry Andric llvm::StringRef Name, 14305f757f3fSDimitry Andric const GlobalFunctionInfo &Info, 14315f757f3fSDimitry Andric VersionTuple SwiftVersion) { 14325f757f3fSDimitry Andric IdentifierID NameID = Implementation->getIdentifier(Name); 1433*0fca6ea1SDimitry Andric SingleDeclTableKey Key(Ctx, NameID); 14345f757f3fSDimitry Andric Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info}); 14355f757f3fSDimitry Andric } 14365f757f3fSDimitry Andric 14375f757f3fSDimitry Andric void APINotesWriter::addEnumConstant(llvm::StringRef Name, 14385f757f3fSDimitry Andric const EnumConstantInfo &Info, 14395f757f3fSDimitry Andric VersionTuple SwiftVersion) { 14405f757f3fSDimitry Andric IdentifierID EnumConstantID = Implementation->getIdentifier(Name); 14415f757f3fSDimitry Andric Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info}); 14425f757f3fSDimitry Andric } 14435f757f3fSDimitry Andric 14445f757f3fSDimitry Andric void APINotesWriter::addTag(std::optional<Context> Ctx, llvm::StringRef Name, 14455f757f3fSDimitry Andric const TagInfo &Info, VersionTuple SwiftVersion) { 14465f757f3fSDimitry Andric IdentifierID TagID = Implementation->getIdentifier(Name); 1447*0fca6ea1SDimitry Andric SingleDeclTableKey Key(Ctx, TagID); 14485f757f3fSDimitry Andric Implementation->Tags[Key].push_back({SwiftVersion, Info}); 14495f757f3fSDimitry Andric } 14505f757f3fSDimitry Andric 14515f757f3fSDimitry Andric void APINotesWriter::addTypedef(std::optional<Context> Ctx, 14525f757f3fSDimitry Andric llvm::StringRef Name, const TypedefInfo &Info, 14535f757f3fSDimitry Andric VersionTuple SwiftVersion) { 14545f757f3fSDimitry Andric IdentifierID TypedefID = Implementation->getIdentifier(Name); 1455*0fca6ea1SDimitry Andric SingleDeclTableKey Key(Ctx, TypedefID); 14565f757f3fSDimitry Andric Implementation->Typedefs[Key].push_back({SwiftVersion, Info}); 14575f757f3fSDimitry Andric } 14585f757f3fSDimitry Andric } // namespace api_notes 14595f757f3fSDimitry Andric } // namespace clang 1460