|
13 | 13 | #include "Serialization.h"
|
14 | 14 | #include "SILFormat.h"
|
15 | 15 | #include "swift/AST/AST.h"
|
| 16 | +#include "swift/AST/ASTMangler.h" |
16 | 17 | #include "swift/AST/ASTWalker.h"
|
17 | 18 | #include "swift/AST/DiagnosticsCommon.h"
|
18 | 19 | #include "swift/AST/ForeignErrorConvention.h"
|
19 | 20 | #include "swift/AST/GenericEnvironment.h"
|
20 | 21 | #include "swift/AST/Initializer.h"
|
21 | 22 | #include "swift/AST/LinkLibrary.h"
|
22 |
| -#include "swift/AST/Mangle.h" |
23 | 23 | #include "swift/AST/ProtocolConformance.h"
|
24 | 24 | #include "swift/AST/ASTMangler.h"
|
25 | 25 | #include "swift/AST/RawComment.h"
|
@@ -112,6 +112,74 @@ namespace {
|
112 | 112 | }
|
113 | 113 | };
|
114 | 114 |
|
| 115 | + class ExtensionTableInfo { |
| 116 | + serialization::Serializer &Serializer; |
| 117 | + llvm::SmallDenseMap<const NominalTypeDecl *,std::string,4> MangledNameCache; |
| 118 | + |
| 119 | + public: |
| 120 | + explicit ExtensionTableInfo(serialization::Serializer &serializer) |
| 121 | + : Serializer(serializer) {} |
| 122 | + |
| 123 | + using key_type = Identifier; |
| 124 | + using key_type_ref = key_type; |
| 125 | + using data_type = Serializer::ExtensionTableData; |
| 126 | + using data_type_ref = const data_type &; |
| 127 | + using hash_value_type = uint32_t; |
| 128 | + using offset_type = unsigned; |
| 129 | + |
| 130 | + hash_value_type ComputeHash(key_type_ref key) { |
| 131 | + assert(!key.empty()); |
| 132 | + return llvm::HashString(key.str()); |
| 133 | + } |
| 134 | + |
| 135 | + int32_t getNameDataForBase(const NominalTypeDecl *nominal, |
| 136 | + StringRef *dataToWrite = nullptr) { |
| 137 | + if (nominal->getDeclContext()->isModuleScopeContext()) |
| 138 | + return -Serializer.addModuleRef(nominal->getParentModule()); |
| 139 | + |
| 140 | + auto &mangledName = MangledNameCache[nominal]; |
| 141 | + if (mangledName.empty()) |
| 142 | + mangledName = NewMangling::ASTMangler().mangleNominalType(nominal); |
| 143 | + |
| 144 | + assert(llvm::isUInt<31>(mangledName.size())); |
| 145 | + if (dataToWrite) |
| 146 | + *dataToWrite = mangledName; |
| 147 | + return mangledName.size(); |
| 148 | + } |
| 149 | + |
| 150 | + std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &out, |
| 151 | + key_type_ref key, |
| 152 | + data_type_ref data) { |
| 153 | + uint32_t keyLength = key.str().size(); |
| 154 | + uint32_t dataLength = (sizeof(uint32_t) * 2) * data.size(); |
| 155 | + for (auto dataPair : data) { |
| 156 | + int32_t nameData = getNameDataForBase(dataPair.first); |
| 157 | + if (nameData > 0) |
| 158 | + dataLength += nameData; |
| 159 | + } |
| 160 | + endian::Writer<little> writer(out); |
| 161 | + writer.write<uint16_t>(keyLength); |
| 162 | + writer.write<uint16_t>(dataLength); |
| 163 | + return { keyLength, dataLength }; |
| 164 | + } |
| 165 | + |
| 166 | + void EmitKey(raw_ostream &out, key_type_ref key, unsigned len) { |
| 167 | + out << key.str(); |
| 168 | + } |
| 169 | + |
| 170 | + void EmitData(raw_ostream &out, key_type_ref key, data_type_ref data, |
| 171 | + unsigned len) { |
| 172 | + static_assert(declIDFitsIn32Bits(), "DeclID too large"); |
| 173 | + endian::Writer<little> writer(out); |
| 174 | + for (auto entry : data) { |
| 175 | + StringRef dataToWrite; |
| 176 | + writer.write<uint32_t>(entry.second); |
| 177 | + writer.write<int32_t>(getNameDataForBase(entry.first, &dataToWrite)); |
| 178 | + out << dataToWrite; |
| 179 | + } |
| 180 | + } |
| 181 | + }; |
| 182 | + |
115 | 183 | class LocalDeclTableInfo {
|
116 | 184 | public:
|
117 | 185 | using key_type = std::string;
|
@@ -3592,6 +3660,32 @@ static void writeDeclTable(const index_block::DeclListLayout &DeclList,
|
3592 | 3660 | DeclList.emit(scratch, kind, tableOffset, hashTableBlob);
|
3593 | 3661 | }
|
3594 | 3662 |
|
| 3663 | +static void |
| 3664 | +writeExtensionTable(const index_block::ExtensionTableLayout &ExtensionTable, |
| 3665 | + const Serializer::ExtensionTable &table, |
| 3666 | + Serializer &serializer) { |
| 3667 | + if (table.empty()) |
| 3668 | + return; |
| 3669 | + |
| 3670 | + SmallVector<uint64_t, 8> scratch; |
| 3671 | + llvm::SmallString<4096> hashTableBlob; |
| 3672 | + uint32_t tableOffset; |
| 3673 | + { |
| 3674 | + llvm::OnDiskChainedHashTableGenerator<ExtensionTableInfo> generator; |
| 3675 | + ExtensionTableInfo info{serializer}; |
| 3676 | + for (auto &entry : table) { |
| 3677 | + generator.insert(entry.first, entry.second, info); |
| 3678 | + } |
| 3679 | + |
| 3680 | + llvm::raw_svector_ostream blobStream(hashTableBlob); |
| 3681 | + // Make sure that no bucket is at offset 0 |
| 3682 | + endian::Writer<little>(blobStream).write<uint32_t>(0); |
| 3683 | + tableOffset = generator.Emit(blobStream, info); |
| 3684 | + } |
| 3685 | + |
| 3686 | + ExtensionTable.emit(scratch, tableOffset, hashTableBlob); |
| 3687 | +} |
| 3688 | + |
3595 | 3689 | static void writeLocalDeclTable(const index_block::DeclListLayout &DeclList,
|
3596 | 3690 | index_block::RecordKind kind,
|
3597 | 3691 | LocalTypeHashTableGenerator &generator) {
|
@@ -4158,11 +4252,12 @@ static void collectInterestingNestedDeclarations(
|
4158 | 4252 |
|
4159 | 4253 | void Serializer::writeAST(ModuleOrSourceFile DC,
|
4160 | 4254 | bool enableNestedTypeLookupTable) {
|
4161 |
| - DeclTable topLevelDecls, extensionDecls, operatorDecls, operatorMethodDecls; |
| 4255 | + DeclTable topLevelDecls, operatorDecls, operatorMethodDecls; |
4162 | 4256 | DeclTable precedenceGroupDecls;
|
4163 | 4257 | ObjCMethodTable objcMethods;
|
4164 | 4258 | NestedTypeDeclsTable nestedTypeDecls;
|
4165 | 4259 | LocalTypeHashTableGenerator localTypeGenerator;
|
| 4260 | + ExtensionTable extensionDecls; |
4166 | 4261 | bool hasLocalTypes = false;
|
4167 | 4262 |
|
4168 | 4263 | Optional<DeclID> entryPointClassID;
|
@@ -4196,7 +4291,7 @@ void Serializer::writeAST(ModuleOrSourceFile DC,
|
4196 | 4291 | Type extendedTy = ED->getExtendedType();
|
4197 | 4292 | const NominalTypeDecl *extendedNominal = extendedTy->getAnyNominal();
|
4198 | 4293 | extensionDecls[extendedNominal->getName()]
|
4199 |
| - .push_back({ getKindForTable(extendedNominal), addDeclRef(D) }); |
| 4294 | + .push_back({ extendedNominal, addDeclRef(D) }); |
4200 | 4295 | } else if (auto OD = dyn_cast<OperatorDecl>(D)) {
|
4201 | 4296 | operatorDecls[OD->getName()]
|
4202 | 4297 | .push_back({ getStableFixity(OD->getKind()), addDeclRef(D) });
|
@@ -4264,13 +4359,17 @@ void Serializer::writeAST(ModuleOrSourceFile DC,
|
4264 | 4359 | writeDeclTable(DeclList, index_block::TOP_LEVEL_DECLS, topLevelDecls);
|
4265 | 4360 | writeDeclTable(DeclList, index_block::OPERATORS, operatorDecls);
|
4266 | 4361 | writeDeclTable(DeclList, index_block::PRECEDENCE_GROUPS, precedenceGroupDecls);
|
4267 |
| - writeDeclTable(DeclList, index_block::EXTENSIONS, extensionDecls); |
4268 | 4362 | writeDeclTable(DeclList, index_block::CLASS_MEMBERS, ClassMembersByName);
|
4269 | 4363 | writeDeclTable(DeclList, index_block::OPERATOR_METHODS, operatorMethodDecls);
|
4270 | 4364 | if (hasLocalTypes)
|
4271 | 4365 | writeLocalDeclTable(DeclList, index_block::LOCAL_TYPE_DECLS,
|
4272 | 4366 | localTypeGenerator);
|
4273 | 4367 |
|
| 4368 | + if (!extensionDecls.empty()) { |
| 4369 | + index_block::ExtensionTableLayout ExtensionTable(Out); |
| 4370 | + writeExtensionTable(ExtensionTable, extensionDecls, *this); |
| 4371 | + } |
| 4372 | + |
4274 | 4373 | index_block::ObjCMethodTableLayout ObjCMethodTable(Out);
|
4275 | 4374 | writeObjCMethodTable(ObjCMethodTable, objcMethods);
|
4276 | 4375 |
|
|
0 commit comments