@@ -64,6 +64,7 @@ namespace {
6464
6565 class BaseNameToEntitiesTableReaderInfo ;
6666 class GlobalsAsMembersTableReaderInfo ;
67+ class AvailabilityDomainsTableReaderInfo ;
6768
6869 using SerializedBaseNameToEntitiesTable =
6970 llvm::OnDiskIterableChainedHashTable<BaseNameToEntitiesTableReaderInfo>;
@@ -73,6 +74,9 @@ namespace {
7374
7475 using SerializedGlobalsAsMembersIndex =
7576 llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
77+
78+ using SerializedAvailabilityDomainsTable =
79+ llvm::OnDiskIterableChainedHashTable<AvailabilityDomainsTableReaderInfo>;
7680} // end anonymous namespace
7781
7882namespace swift {
@@ -114,6 +118,8 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
114118
115119 std::unique_ptr<SerializedBaseNameToEntitiesTable> SerializedTable;
116120 ArrayRef<clang::serialization::DeclID> Categories;
121+ // FIXME: [availability] Remove this when Clang supports domain lookup.
122+ std::unique_ptr<SerializedAvailabilityDomainsTable> AvailabilityDomainsTable;
117123 std::unique_ptr<SerializedGlobalsAsMembersTable> GlobalsAsMembersTable;
118124 std::unique_ptr<SerializedGlobalsAsMembersIndex> GlobalsAsMembersIndex;
119125
@@ -124,13 +130,16 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
124130 std::unique_ptr<SerializedBaseNameToEntitiesTable>
125131 serializedTable,
126132 ArrayRef<clang::serialization::DeclID> categories,
133+ std::unique_ptr<SerializedAvailabilityDomainsTable>
134+ availabilityDomainsTable,
127135 std::unique_ptr<SerializedGlobalsAsMembersTable>
128136 globalsAsMembersTable,
129137 std::unique_ptr<SerializedGlobalsAsMembersIndex>
130138 globalsAsMembersIndex)
131139 : ModuleFileExtensionReader(extension), Reader(reader),
132140 ModuleFile (moduleFile), OnRemove(onRemove),
133141 SerializedTable(std::move(serializedTable)), Categories(categories),
142+ AvailabilityDomainsTable(std::move(availabilityDomainsTable)),
134143 GlobalsAsMembersTable(std::move(globalsAsMembersTable)),
135144 GlobalsAsMembersIndex(std::move(globalsAsMembersIndex)) {}
136145
@@ -185,6 +194,12 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
185194 bool lookupGlobalsAsMembers (
186195 SerializedSwiftName baseName,
187196 SmallVectorImpl<SwiftLookupTable::FullTableEntry> &entries);
197+
198+ SmallVector<StringRef, 4 > getAvailabilityDomainNames ();
199+
200+ // / Retreve the decl ID representing the availability domain with the given
201+ // / name.
202+ clang::serialization::DeclID lookupAvailabilityDomain (StringRef domainName);
188203};
189204} // namespace swift
190205
@@ -352,7 +367,7 @@ void SwiftLookupTable::addCategory(clang::ObjCCategoryDecl *category) {
352367
353368void SwiftLookupTable::addAvailabilityDomainDecl (StringRef name,
354369 clang::VarDecl *decl) {
355- AvailabilityDomains.insert ({name, StoredSingleEntry ( decl) });
370+ AvailabilityDomains.insert ({name, decl});
356371}
357372
358373bool SwiftLookupTable::resolveUnresolvedEntries (
@@ -717,15 +732,36 @@ SwiftLookupTable::lookupGlobalsAsMembers(SerializedSwiftName baseName,
717732 return lookupGlobalsAsMembersImpl (baseName, *storedContext);
718733}
719734
735+ // FIXME: [availability] Remove this once Clang has a lookup table.
720736clang::VarDecl *SwiftLookupTable::lookupAvailabilityDomainDecl (StringRef name) {
721- // FIXME: [availability] Remove this once Clang has a lookup table.
722- auto result = AvailabilityDomains.find (name);
723- if (result == AvailabilityDomains.end ())
737+ // If the name is empty, there is nothing to find.
738+ if (name.empty ())
724739 return nullptr ;
725740
726- auto &entry = result->second ;
727- DEBUG_ASSERT (entry.isASTNodeEntry ());
728- return static_cast <clang::VarDecl *>(entry.getASTNode ());
741+ // See if we have an existing cached lookup result.
742+ auto known = AvailabilityDomains.find (name);
743+ if (known != AvailabilityDomains.end ())
744+ return known->second ;
745+
746+ // If there's no reader, we've found all there is to find.
747+ if (!Reader)
748+ return nullptr ;
749+
750+ // Look up this domain in the module file.
751+ clang::VarDecl *result = nullptr ;
752+ auto declID = Reader->lookupAvailabilityDomain (name);
753+ if (declID) {
754+ auto localID = clang::LocalDeclID::get (Reader->getASTReader (),
755+ Reader->getModuleFile (), declID);
756+ result = cast_or_null<clang::VarDecl>(
757+ Reader->getASTReader ().GetLocalDecl (Reader->getModuleFile (), localID));
758+ }
759+
760+ // Add the result to the table (whether we found a decl or not) so that we
761+ // don't look again.
762+ AvailabilityDomains.insert ({name, result});
763+
764+ return result;
729765}
730766
731767SmallVector<SwiftLookupTable::SingleEntry, 4 >
@@ -936,6 +972,10 @@ void SwiftLookupTable::deserializeAll() {
936972 for (auto context : Reader->getGlobalsAsMembersContexts ()) {
937973 (void )allGlobalsAsMembersInContext (context);
938974 }
975+
976+ for (auto domainName : Reader->getAvailabilityDomainNames ()) {
977+ (void )lookupAvailabilityDomainDecl (domainName);
978+ }
939979}
940980
941981// / Print a stored context to the given output stream for debugging purposes.
@@ -1066,6 +1106,22 @@ void SwiftLookupTable::dump(raw_ostream &os) const {
10661106 os << " \n " ;
10671107 }
10681108 }
1109+
1110+ if (!AvailabilityDomains.empty ()) {
1111+ os << " Availability domains:\n " ;
1112+ SmallVector<StringRef, 4 > domainNames;
1113+ for (const auto &entry : AvailabilityDomains) {
1114+ domainNames.push_back (entry.first );
1115+ }
1116+ llvm::array_pod_sort (domainNames.begin (), domainNames.end ());
1117+
1118+ for (auto domainName : domainNames) {
1119+ os << " " << domainName << " : " ;
1120+
1121+ auto *domainDecl = AvailabilityDomains.find (domainName)->second ;
1122+ os << (domainDecl ? domainDecl->getName () : " <nullptr>" ) << " \n " ;
1123+ }
1124+ }
10691125}
10701126
10711127// ---------------------------------------------------------------------------
@@ -1095,6 +1151,10 @@ namespace {
10951151 // / Record that contains the mapping from contexts to the list of
10961152 // / globals that will be injected as members into those contexts.
10971153 GLOBALS_AS_MEMBERS_INDEX_RECORD_ID,
1154+
1155+ // FIXME: [availability] Remove this when Clang supports domain lookup.
1156+ // / Record that contains the mapping from domain names to domain decls.
1157+ AVAILABILITY_DOMAINS_ID,
10981158 };
10991159
11001160 using BaseNameToEntitiesTableRecordLayout
@@ -1109,6 +1169,9 @@ namespace {
11091169 using GlobalsAsMembersIndexRecordLayout
11101170 = BCRecordLayout<GLOBALS_AS_MEMBERS_INDEX_RECORD_ID, BCVBR<16 >, BCBlob>;
11111171
1172+ using AvailabilityDomainsTableRecordLayout =
1173+ BCRecordLayout<AVAILABILITY_DOMAINS_ID, BCVBR<16 >, BCBlob>;
1174+
11121175 constexpr size_t SizeOfEmittedStoredSingleEntry
11131176 = sizeof (StoredSingleEntry::SerializationID)
11141177 + sizeof (StoredSingleEntry::SubmoduleID);
@@ -1303,6 +1366,39 @@ namespace {
13031366 }
13041367 }
13051368 };
1369+
1370+ // FIXME: [availability] Remove this when Clang supports domain lookup.
1371+ // / Trait used to write the on-disk hash table for the identifier ->
1372+ // / availability domain table.
1373+ class AvailabilityDomainsTableWriterInfo {
1374+ public:
1375+ using key_type = StringRef;
1376+ using key_type_ref = key_type;
1377+ using data_type = clang::serialization::DeclID;
1378+ using data_type_ref = const data_type &;
1379+ using hash_value_type = uint32_t ;
1380+ using offset_type = unsigned ;
1381+
1382+ hash_value_type ComputeHash (key_type_ref key) { return llvm::djbHash (key); }
1383+
1384+ std::pair<unsigned , unsigned >
1385+ EmitKeyDataLength (raw_ostream &os, key_type_ref key, data_type_ref) {
1386+ uint32_t keyLength = key.size ();
1387+ uint32_t dataLength = sizeof (data_type);
1388+
1389+ llvm::support::endian::Writer writer (os, llvm::endianness::little);
1390+ writer.write <uint16_t >(keyLength);
1391+ writer.write <uint16_t >(dataLength);
1392+ return {keyLength, dataLength};
1393+ }
1394+
1395+ void EmitKey (raw_ostream &os, key_type_ref key, unsigned ) { os << key; }
1396+
1397+ void EmitData (raw_ostream &os, key_type_ref, data_type_ref data, unsigned ) {
1398+ llvm::support::endian::Writer writer (os, llvm::endianness::little);
1399+ writer.write <data_type>(data);
1400+ }
1401+ };
13061402} // end anonymous namespace
13071403
13081404void SwiftLookupTableWriter::writeExtensionContents (
@@ -1414,6 +1510,35 @@ void SwiftLookupTableWriter::writeExtensionContents(
14141510 GlobalsAsMembersIndexRecordLayout layout (stream);
14151511 layout.emit (ScratchRecord, tableOffset, hashTableBlob);
14161512 }
1513+
1514+ if (!table.AvailabilityDomains .empty ()) {
1515+ // Sort the availability domain names.
1516+ SmallVector<StringRef, 4 > domainNames;
1517+ for (const auto &entry : table.AvailabilityDomains )
1518+ domainNames.push_back (entry.first );
1519+ llvm::array_pod_sort (domainNames.begin (), domainNames.end ());
1520+
1521+ llvm::SmallString<4096 > hashTableBlob;
1522+ uint32_t tableOffset;
1523+ {
1524+ llvm::OnDiskChainedHashTableGenerator<AvailabilityDomainsTableWriterInfo>
1525+ generator;
1526+ AvailabilityDomainsTableWriterInfo info;
1527+
1528+ for (auto domainName : domainNames) {
1529+ auto domainDecl = table.AvailabilityDomains [domainName];
1530+ auto declID = Writer.getDeclID (domainDecl).getRawValue ();
1531+ generator.insert (domainName, declID, info);
1532+ }
1533+
1534+ llvm::raw_svector_ostream blobStream (hashTableBlob);
1535+ // Make sure that no bucket is at offset 0
1536+ endian::write<uint32_t >(blobStream, 0 , llvm::endianness::little);
1537+ tableOffset = generator.Emit (blobStream, info);
1538+ }
1539+ AvailabilityDomainsTableRecordLayout layout (stream);
1540+ layout.emit (ScratchRecord, tableOffset, hashTableBlob);
1541+ }
14171542}
14181543
14191544namespace {
@@ -1564,6 +1689,47 @@ namespace {
15641689 return result;
15651690 }
15661691 };
1692+
1693+ // FIXME: [availability] Remove this when Clang supports domain lookup.
1694+ // / Used to deserialize the on-disk identifier -> availability domain table.
1695+ class AvailabilityDomainsTableReaderInfo {
1696+ public:
1697+ using internal_key_type = llvm::StringRef;
1698+ using external_key_type = internal_key_type;
1699+ using data_type = clang::serialization::DeclID;
1700+ using hash_value_type = uint32_t ;
1701+ using offset_type = unsigned ;
1702+
1703+ internal_key_type GetInternalKey (external_key_type key) { return key; }
1704+ external_key_type GetExternalKey (internal_key_type key) { return key; }
1705+
1706+ hash_value_type ComputeHash (internal_key_type key) {
1707+ return llvm::djbHash (key);
1708+ }
1709+
1710+ static bool EqualKey (internal_key_type lhs, internal_key_type rhs) {
1711+ return lhs == rhs;
1712+ }
1713+
1714+ static std::pair<unsigned , unsigned >
1715+ ReadKeyDataLength (const uint8_t *&data) {
1716+ unsigned keyLength =
1717+ endian::readNext<uint16_t , llvm::endianness::little>(data);
1718+ unsigned dataLength =
1719+ endian::readNext<uint16_t , llvm::endianness::little>(data);
1720+ return {keyLength, dataLength};
1721+ }
1722+
1723+ static internal_key_type ReadKey (const uint8_t *data, unsigned length) {
1724+ return llvm::StringRef (reinterpret_cast <const char *>(data), length);
1725+ }
1726+
1727+ static data_type ReadData (internal_key_type key, const uint8_t *data,
1728+ unsigned length) {
1729+ return endian::readNext<data_type, llvm::endianness::little>(data);
1730+ }
1731+ };
1732+
15671733} // end anonymous namespace
15681734
15691735clang::NamedDecl *SwiftLookupTable::mapStoredDecl (StoredSingleEntry &entry) {
@@ -1673,6 +1839,8 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
16731839 std::unique_ptr<SerializedGlobalsAsMembersIndex> globalsAsMembersIndex;
16741840 std::unique_ptr<SerializedGlobalsAsMembersTable> globalsAsMembersTable;
16751841 ArrayRef<clang::serialization::DeclID> categories;
1842+ std::unique_ptr<SerializedAvailabilityDomainsTable> availabilityDomainsTable;
1843+
16761844 while (next.Kind != llvm::BitstreamEntry::EndBlock) {
16771845 if (next.Kind == llvm::BitstreamEntry::Error)
16781846 return nullptr ;
@@ -1764,6 +1932,20 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
17641932 break ;
17651933 }
17661934
1935+ case AVAILABILITY_DOMAINS_ID: {
1936+ // Already saw the availability domains table.
1937+ if (availabilityDomainsTable)
1938+ return nullptr ;
1939+
1940+ uint32_t tableOffset;
1941+ AvailabilityDomainsTableRecordLayout::readRecord (scratch, tableOffset);
1942+ auto base = reinterpret_cast <const uint8_t *>(blobData.data ());
1943+
1944+ availabilityDomainsTable.reset (SerializedAvailabilityDomainsTable::Create (
1945+ base + tableOffset, base + sizeof (uint32_t ), base));
1946+ break ;
1947+ }
1948+
17671949 default :
17681950 // Unknown record, possibly for use by a future version of the
17691951 // module format.
@@ -1787,6 +1969,7 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
17871969 return std::unique_ptr<SwiftLookupTableReader>(
17881970 new SwiftLookupTableReader (extension, reader, moduleFile, onRemove,
17891971 std::move (serializedTable), categories,
1972+ std::move (availabilityDomainsTable),
17901973 std::move (globalsAsMembersTable),
17911974 std::move (globalsAsMembersIndex)));
17921975
@@ -1862,6 +2045,30 @@ bool SwiftLookupTableReader::lookupGlobalsAsMembers(
18622045 return true ;
18632046}
18642047
2048+ SmallVector<StringRef, 4 > SwiftLookupTableReader::getAvailabilityDomainNames () {
2049+ SmallVector<StringRef, 4 > results;
2050+ if (!AvailabilityDomainsTable)
2051+ return {};
2052+
2053+ for (auto name : AvailabilityDomainsTable->keys ()) {
2054+ results.push_back (name);
2055+ }
2056+ return results;
2057+ }
2058+
2059+ clang::serialization::DeclID
2060+ SwiftLookupTableReader::lookupAvailabilityDomain (StringRef domainName) {
2061+ if (!AvailabilityDomainsTable)
2062+ return {};
2063+
2064+ // Look for an entry with this context name.
2065+ auto known = AvailabilityDomainsTable->find (domainName);
2066+ if (known == AvailabilityDomainsTable->end ())
2067+ return {};
2068+
2069+ return *known;
2070+ }
2071+
18652072clang::ModuleFileExtensionMetadata
18662073SwiftNameLookupExtension::getExtensionMetadata () const {
18672074 clang::ModuleFileExtensionMetadata metadata;
0 commit comments