@@ -64,6 +64,7 @@ namespace {
64
64
65
65
class BaseNameToEntitiesTableReaderInfo ;
66
66
class GlobalsAsMembersTableReaderInfo ;
67
+ class AvailabilityDomainsTableReaderInfo ;
67
68
68
69
using SerializedBaseNameToEntitiesTable =
69
70
llvm::OnDiskIterableChainedHashTable<BaseNameToEntitiesTableReaderInfo>;
@@ -73,6 +74,9 @@ namespace {
73
74
74
75
using SerializedGlobalsAsMembersIndex =
75
76
llvm::OnDiskIterableChainedHashTable<GlobalsAsMembersTableReaderInfo>;
77
+
78
+ using SerializedAvailabilityDomainsTable =
79
+ llvm::OnDiskIterableChainedHashTable<AvailabilityDomainsTableReaderInfo>;
76
80
} // end anonymous namespace
77
81
78
82
namespace swift {
@@ -114,6 +118,8 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
114
118
115
119
std::unique_ptr<SerializedBaseNameToEntitiesTable> SerializedTable;
116
120
ArrayRef<clang::serialization::DeclID> Categories;
121
+ // FIXME: [availability] Remove this when Clang supports domain lookup.
122
+ std::unique_ptr<SerializedAvailabilityDomainsTable> AvailabilityDomainsTable;
117
123
std::unique_ptr<SerializedGlobalsAsMembersTable> GlobalsAsMembersTable;
118
124
std::unique_ptr<SerializedGlobalsAsMembersIndex> GlobalsAsMembersIndex;
119
125
@@ -124,13 +130,16 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
124
130
std::unique_ptr<SerializedBaseNameToEntitiesTable>
125
131
serializedTable,
126
132
ArrayRef<clang::serialization::DeclID> categories,
133
+ std::unique_ptr<SerializedAvailabilityDomainsTable>
134
+ availabilityDomainsTable,
127
135
std::unique_ptr<SerializedGlobalsAsMembersTable>
128
136
globalsAsMembersTable,
129
137
std::unique_ptr<SerializedGlobalsAsMembersIndex>
130
138
globalsAsMembersIndex)
131
139
: ModuleFileExtensionReader(extension), Reader(reader),
132
140
ModuleFile (moduleFile), OnRemove(onRemove),
133
141
SerializedTable(std::move(serializedTable)), Categories(categories),
142
+ AvailabilityDomainsTable(std::move(availabilityDomainsTable)),
134
143
GlobalsAsMembersTable(std::move(globalsAsMembersTable)),
135
144
GlobalsAsMembersIndex(std::move(globalsAsMembersIndex)) {}
136
145
@@ -185,6 +194,12 @@ class SwiftLookupTableReader : public clang::ModuleFileExtensionReader {
185
194
bool lookupGlobalsAsMembers (
186
195
SerializedSwiftName baseName,
187
196
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);
188
203
};
189
204
} // namespace swift
190
205
@@ -352,7 +367,7 @@ void SwiftLookupTable::addCategory(clang::ObjCCategoryDecl *category) {
352
367
353
368
void SwiftLookupTable::addAvailabilityDomainDecl (StringRef name,
354
369
clang::VarDecl *decl) {
355
- AvailabilityDomains.insert ({name, StoredSingleEntry ( decl) });
370
+ AvailabilityDomains.insert ({name, decl});
356
371
}
357
372
358
373
bool SwiftLookupTable::resolveUnresolvedEntries (
@@ -717,15 +732,36 @@ SwiftLookupTable::lookupGlobalsAsMembers(SerializedSwiftName baseName,
717
732
return lookupGlobalsAsMembersImpl (baseName, *storedContext);
718
733
}
719
734
735
+ // FIXME: [availability] Remove this once Clang has a lookup table.
720
736
clang::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 ())
724
739
return nullptr ;
725
740
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;
729
765
}
730
766
731
767
SmallVector<SwiftLookupTable::SingleEntry, 4 >
@@ -936,6 +972,10 @@ void SwiftLookupTable::deserializeAll() {
936
972
for (auto context : Reader->getGlobalsAsMembersContexts ()) {
937
973
(void )allGlobalsAsMembersInContext (context);
938
974
}
975
+
976
+ for (auto domainName : Reader->getAvailabilityDomainNames ()) {
977
+ (void )lookupAvailabilityDomainDecl (domainName);
978
+ }
939
979
}
940
980
941
981
// / Print a stored context to the given output stream for debugging purposes.
@@ -1066,6 +1106,22 @@ void SwiftLookupTable::dump(raw_ostream &os) const {
1066
1106
os << " \n " ;
1067
1107
}
1068
1108
}
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
+ }
1069
1125
}
1070
1126
1071
1127
// ---------------------------------------------------------------------------
@@ -1095,6 +1151,10 @@ namespace {
1095
1151
// / Record that contains the mapping from contexts to the list of
1096
1152
// / globals that will be injected as members into those contexts.
1097
1153
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,
1098
1158
};
1099
1159
1100
1160
using BaseNameToEntitiesTableRecordLayout
@@ -1109,6 +1169,9 @@ namespace {
1109
1169
using GlobalsAsMembersIndexRecordLayout
1110
1170
= BCRecordLayout<GLOBALS_AS_MEMBERS_INDEX_RECORD_ID, BCVBR<16 >, BCBlob>;
1111
1171
1172
+ using AvailabilityDomainsTableRecordLayout =
1173
+ BCRecordLayout<AVAILABILITY_DOMAINS_ID, BCVBR<16 >, BCBlob>;
1174
+
1112
1175
constexpr size_t SizeOfEmittedStoredSingleEntry
1113
1176
= sizeof (StoredSingleEntry::SerializationID)
1114
1177
+ sizeof (StoredSingleEntry::SubmoduleID);
@@ -1303,6 +1366,39 @@ namespace {
1303
1366
}
1304
1367
}
1305
1368
};
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
+ };
1306
1402
} // end anonymous namespace
1307
1403
1308
1404
void SwiftLookupTableWriter::writeExtensionContents (
@@ -1414,6 +1510,35 @@ void SwiftLookupTableWriter::writeExtensionContents(
1414
1510
GlobalsAsMembersIndexRecordLayout layout (stream);
1415
1511
layout.emit (ScratchRecord, tableOffset, hashTableBlob);
1416
1512
}
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
+ }
1417
1542
}
1418
1543
1419
1544
namespace {
@@ -1564,6 +1689,47 @@ namespace {
1564
1689
return result;
1565
1690
}
1566
1691
};
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
+
1567
1733
} // end anonymous namespace
1568
1734
1569
1735
clang::NamedDecl *SwiftLookupTable::mapStoredDecl (StoredSingleEntry &entry) {
@@ -1673,6 +1839,8 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
1673
1839
std::unique_ptr<SerializedGlobalsAsMembersIndex> globalsAsMembersIndex;
1674
1840
std::unique_ptr<SerializedGlobalsAsMembersTable> globalsAsMembersTable;
1675
1841
ArrayRef<clang::serialization::DeclID> categories;
1842
+ std::unique_ptr<SerializedAvailabilityDomainsTable> availabilityDomainsTable;
1843
+
1676
1844
while (next.Kind != llvm::BitstreamEntry::EndBlock) {
1677
1845
if (next.Kind == llvm::BitstreamEntry::Error)
1678
1846
return nullptr ;
@@ -1764,6 +1932,20 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
1764
1932
break ;
1765
1933
}
1766
1934
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
+
1767
1949
default :
1768
1950
// Unknown record, possibly for use by a future version of the
1769
1951
// module format.
@@ -1787,6 +1969,7 @@ SwiftLookupTableReader::create(clang::ModuleFileExtension *extension,
1787
1969
return std::unique_ptr<SwiftLookupTableReader>(
1788
1970
new SwiftLookupTableReader (extension, reader, moduleFile, onRemove,
1789
1971
std::move (serializedTable), categories,
1972
+ std::move (availabilityDomainsTable),
1790
1973
std::move (globalsAsMembersTable),
1791
1974
std::move (globalsAsMembersIndex)));
1792
1975
@@ -1862,6 +2045,30 @@ bool SwiftLookupTableReader::lookupGlobalsAsMembers(
1862
2045
return true ;
1863
2046
}
1864
2047
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
+
1865
2072
clang::ModuleFileExtensionMetadata
1866
2073
SwiftNameLookupExtension::getExtensionMetadata () const {
1867
2074
clang::ModuleFileExtensionMetadata metadata;
0 commit comments