Skip to content

Commit cfc2dda

Browse files
authored
Merge pull request #24705 from eeckstein/fix-vtable-serialization
Serialization: use the mangled class name for serializing vtables.
2 parents 6cca050 + c957c50 commit cfc2dda

File tree

8 files changed

+70
-11
lines changed

8 files changed

+70
-11
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 490; // dependency directories
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 491; // mangled class names as vtable keys
5656

5757
using DeclIDField = BCFixed<31>;
5858

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,7 @@ class SerializedSILLoader {
6161
lookupSILFunction(StringRef Name, bool declarationOnly = false,
6262
Optional<SILLinkage> linkage = None);
6363
bool hasSILFunction(StringRef Name, Optional<SILLinkage> linkage = None);
64-
SILVTable *lookupVTable(Identifier Name);
65-
SILVTable *lookupVTable(const ClassDecl *C) {
66-
return lookupVTable(C->getName());
67-
}
64+
SILVTable *lookupVTable(const ClassDecl *C);
6865
SILWitnessTable *lookupWitnessTable(SILWitnessTable *C);
6966
SILDefaultWitnessTable *lookupDefaultWitnessTable(SILDefaultWitnessTable *C);
7067

lib/Serialization/DeserializeSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2779,10 +2779,10 @@ SILVTable *SILDeserializer::readVTable(DeclID VId) {
27792779
return vT;
27802780
}
27812781

2782-
SILVTable *SILDeserializer::lookupVTable(Identifier Name) {
2782+
SILVTable *SILDeserializer::lookupVTable(StringRef MangledClassName) {
27832783
if (!VTableList)
27842784
return nullptr;
2785-
auto iter = VTableList->find(Name.str());
2785+
auto iter = VTableList->find(MangledClassName);
27862786
if (iter == VTableList->end())
27872787
return nullptr;
27882788

lib/Serialization/DeserializeSIL.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ namespace swift {
141141
SILFunction *lookupSILFunction(StringRef Name,
142142
bool declarationOnly = false);
143143
bool hasSILFunction(StringRef Name, Optional<SILLinkage> Linkage = None);
144-
SILVTable *lookupVTable(Identifier Name);
144+
SILVTable *lookupVTable(StringRef MangledClassName);
145145
SILWitnessTable *lookupWitnessTable(SILWitnessTable *wt);
146146
SILDefaultWitnessTable *
147147
lookupDefaultWitnessTable(SILDefaultWitnessTable *wt);

lib/Serialization/SerializeSIL.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/GenericSignature.h"
1717
#include "swift/AST/Module.h"
1818
#include "swift/AST/ProtocolConformance.h"
19+
#include "swift/AST/ASTMangler.h"
1920
#include "swift/SIL/CFG.h"
2021
#include "swift/SIL/PrettyStackTrace.h"
2122
#include "swift/SIL/SILArgument.h"
@@ -195,6 +196,10 @@ namespace {
195196
/// Additional functions we might need to serialize.
196197
llvm::SmallVector<const SILFunction *, 16> Worklist;
197198

199+
/// String storage for temporarily created strings which are referenced from
200+
/// the tables.
201+
llvm::BumpPtrAllocator StringTable;
202+
198203
std::array<unsigned, 256> SILAbbrCodes;
199204
template <typename Layout>
200205
void registerSILAbbr() {
@@ -2208,7 +2213,17 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) {
22082213
if (!ShouldSerializeAll &&
22092214
vt.getClass()->getEffectiveAccess() < swift::AccessLevel::Public)
22102215
return;
2211-
VTableList[vt.getClass()->getName().str()] = NextVTableID++;
2216+
2217+
// Use the mangled name of the class as a key to distinguish between classes
2218+
// which have the same name (but are in different contexts).
2219+
Mangle::ASTMangler mangler;
2220+
std::string mangledClassName = mangler.mangleNominalType(vt.getClass());
2221+
size_t nameLength = mangledClassName.size();
2222+
char *stringStorage = (char *)StringTable.Allocate(nameLength, 1);
2223+
std::memcpy(stringStorage, mangledClassName.data(), nameLength);
2224+
2225+
VTableList[StringRef(stringStorage, nameLength)] = NextVTableID++;
2226+
22122227
VTableOffset.push_back(Out.GetCurrentBitNo());
22132228
VTableLayout::emitRecord(Out, ScratchRecord, SILAbbrCodes[VTableLayout::Code],
22142229
S.addDeclRef(vt.getClass()),

lib/Serialization/SerializedSILLoader.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/Serialization/ModuleFile.h"
1717
#include "swift/Serialization/SerializedModuleLoader.h"
1818
#include "swift/SIL/SILModule.h"
19+
#include "swift/AST/ASTMangler.h"
1920
#include "llvm/Support/Debug.h"
2021

2122
using namespace swift;
@@ -100,9 +101,12 @@ bool SerializedSILLoader::hasSILFunction(StringRef Name,
100101
}
101102

102103

103-
SILVTable *SerializedSILLoader::lookupVTable(Identifier Name) {
104+
SILVTable *SerializedSILLoader::lookupVTable(const ClassDecl *C) {
105+
Mangle::ASTMangler mangler;
106+
std::string mangledClassName = mangler.mangleNominalType(C);
107+
104108
for (auto &Des : LoadedSILSections) {
105-
if (auto VT = Des->lookupVTable(Name))
109+
if (auto VT = Des->lookupVTable(mangledClassName))
106110
return VT;
107111
}
108112
return nullptr;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
open class B {
3+
public init(data: Int) {
4+
}
5+
}
6+
7+
public struct StructA {
8+
final public class Testclass: B {
9+
}
10+
}
11+
12+
public struct StructB {
13+
final public class Testclass: B {
14+
}
15+
}
16+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -parse-as-library -module-name Classes -emit-module -emit-module-path %t/Classes.swiftmodule %S/Inputs/classes.swift
3+
// RUN: %target-build-swift -parse-as-library -module-name Classes -c -o %t/classes.o %S/Inputs/classes.swift
4+
// RUN: %target-build-swift -I %t %s %t/classes.o -o %t/a.out
5+
// RUN: %target-codesign %t/a.out
6+
// RUN: %target-run %t/a.out | %FileCheck %s
7+
// REQUIRES: executable_test
8+
9+
import Classes
10+
11+
// Check if the right vtable is deserialized in case of two classes which have
12+
// the same name (but are in different contexts).
13+
14+
func testit() {
15+
let a = StructA.Testclass()
16+
// CHECK: true
17+
print(type(of: a) == StructA.Testclass.self)
18+
}
19+
20+
extension StructA.Testclass {
21+
convenience init() {
22+
self.init(data: 0)
23+
}
24+
}
25+
26+
testit()
27+

0 commit comments

Comments
 (0)