mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Serialization] Preserve private discriminators through serialization.
Part of rdar://problem/17632175 Swift SVN r21611
This commit is contained in:
@@ -160,6 +160,8 @@ TRAILING_INFO(GENERIC_PARAM)
|
||||
TRAILING_INFO(GENERIC_REQUIREMENT)
|
||||
TRAILING_INFO(LAST_GENERIC_REQUIREMENT)
|
||||
|
||||
OTHER(DISCRIMINATOR, 249)
|
||||
|
||||
OTHER(NO_CONFORMANCE, 250)
|
||||
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 251)
|
||||
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 252)
|
||||
|
||||
@@ -250,6 +250,8 @@ private:
|
||||
std::unique_ptr<SerializedDeclTable> ClassMembersByName;
|
||||
std::unique_ptr<SerializedDeclTable> OperatorMethodDecls;
|
||||
|
||||
llvm::DenseMap<const ValueDecl *, Identifier> PrivateDiscriminatorsByValue;
|
||||
|
||||
TinyPtrVector<Decl *> ImportDecls;
|
||||
|
||||
using DeclIDVector = SmallVector<serialization::DeclID, 4>;
|
||||
|
||||
@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
|
||||
/// Serialized module format minor version number.
|
||||
///
|
||||
/// When the format changes IN ANY WAY, this number should be incremented.
|
||||
const uint16_t VERSION_MINOR = 131;
|
||||
const uint16_t VERSION_MINOR = 132;
|
||||
|
||||
using DeclID = Fixnum<31>;
|
||||
using DeclIDField = BCFixed<31>;
|
||||
@@ -947,6 +947,13 @@ namespace decls_block {
|
||||
BCFixed<1> // dummy
|
||||
>;
|
||||
|
||||
/// Specifies the discriminator string for a private declaration. This
|
||||
/// identifies the declaration's original source file in some opaque way.
|
||||
using DiscriminatorLayout = BCRecordLayout<
|
||||
DISCRIMINATOR,
|
||||
IdentifierIDField // discriminator string, as an identifier
|
||||
>;
|
||||
|
||||
/// A placeholder for lack of conformance information. Conformances are
|
||||
/// indexed, so simply omitting one would be incorrect.
|
||||
using NoConformanceLayout = BCRecordLayout<
|
||||
|
||||
@@ -1484,6 +1484,25 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
||||
};
|
||||
unsigned recordID;
|
||||
|
||||
class DiscriminatorRAII {
|
||||
ModuleFile &moduleFile;
|
||||
Serialized<Decl *> &declOrOffset;
|
||||
|
||||
public:
|
||||
Identifier discriminator;
|
||||
|
||||
DiscriminatorRAII(ModuleFile &moduleFile,
|
||||
Serialized<Decl *> &declOrOffset)
|
||||
: moduleFile(moduleFile), declOrOffset(declOrOffset) {}
|
||||
|
||||
~DiscriminatorRAII() {
|
||||
if (!discriminator.empty() && declOrOffset.isComplete())
|
||||
if (auto value = dyn_cast_or_null<ValueDecl>(declOrOffset.get()))
|
||||
moduleFile.PrivateDiscriminatorsByValue[value] = discriminator;
|
||||
}
|
||||
};
|
||||
DiscriminatorRAII discriminatorRAII{*this, declOrOffset};
|
||||
|
||||
while (true) {
|
||||
if (entry.Kind != llvm::BitstreamEntry::Record) {
|
||||
// We don't know how to serialize decls represented by sub-blocks.
|
||||
@@ -1614,15 +1633,20 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
|
||||
|
||||
AddAttribute(Attr);
|
||||
|
||||
// Advance bitstream cursor to the next record.
|
||||
entry = DeclTypeCursor.advance();
|
||||
} else if (recordID == decls_block::DISCRIMINATOR) {
|
||||
IdentifierID discriminatorID;
|
||||
decls_block::DiscriminatorLayout::readRecord(scratch, discriminatorID);
|
||||
discriminatorRAII.discriminator = getIdentifier(discriminatorID);
|
||||
|
||||
// Prepare to read the next record.
|
||||
scratch.clear();
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
// Advance bitstream cursor to the next record.
|
||||
entry = DeclTypeCursor.advance();
|
||||
|
||||
// Prepare to read the next record.
|
||||
scratch.clear();
|
||||
}
|
||||
|
||||
PrettyDeclDeserialization stackTraceEntry(
|
||||
|
||||
@@ -1240,6 +1240,7 @@ Optional<BriefAndRawComment> ModuleFile::getCommentForDeclByUSR(StringRef USR) {
|
||||
}
|
||||
|
||||
Identifier ModuleFile::getDiscriminatorForPrivateValue(const ValueDecl *D) {
|
||||
// FIXME: Actually implement this.
|
||||
return FileContext->getParentModule()->Name;
|
||||
Identifier discriminator = PrivateDiscriminatorsByValue.lookup(D);
|
||||
assert(!discriminator.empty() && "no discriminator found for decl");
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
@@ -1448,6 +1448,26 @@ void Serializer::writeDecl(const Decl *D) {
|
||||
writeDeclAttribute(Attr);
|
||||
}
|
||||
|
||||
if (M->Ctx.LangOpts.UsePrivateDiscriminators) {
|
||||
if (auto *value = dyn_cast<ValueDecl>(D)) {
|
||||
if (value->hasAccessibility() &&
|
||||
value->getAccessibility() == Accessibility::Private &&
|
||||
!value->getDeclContext()->isLocalContext()) {
|
||||
// FIXME: We shouldn't need to encode this for /all/ private decls.
|
||||
// In theory we can follow the same rules as mangling and only include
|
||||
// the outermost private context.
|
||||
auto topLevelContext = value->getDeclContext()->getModuleScopeContext();
|
||||
if (auto *enclosingFile = dyn_cast<FileUnit>(topLevelContext)) {
|
||||
Identifier discriminator =
|
||||
enclosingFile->getDiscriminatorForPrivateValue(value);
|
||||
unsigned abbrCode = DeclTypeAbbrCodes[DiscriminatorLayout::Code];
|
||||
DiscriminatorLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
addIdentifierRef(discriminator));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (D->getKind()) {
|
||||
case DeclKind::Import:
|
||||
llvm_unreachable("import decls should not be serialized");
|
||||
@@ -2622,6 +2642,8 @@ void Serializer::writeAllDeclsAndTypes() {
|
||||
registerDeclTypeAbbr<NormalProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<SpecializedProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<InheritedProtocolConformanceLayout>();
|
||||
|
||||
registerDeclTypeAbbr<DiscriminatorLayout>();
|
||||
registerDeclTypeAbbr<DeclContextLayout>();
|
||||
registerDeclTypeAbbr<XRefLayout>();
|
||||
|
||||
|
||||
9
test/SILGen/Inputs/mangling_private_helper.swift
Normal file
9
test/SILGen/Inputs/mangling_private_helper.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
public class Base {
|
||||
private func privateMethod() {}
|
||||
}
|
||||
|
||||
// Demonstrate the need for a vtable entry for privateMethod().
|
||||
// This isn't strictly necessary.
|
||||
private class Subclass : Base {
|
||||
override private func privateMethod() {}
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
// RUN: rm -rf %t && mkdir %t
|
||||
// RUN: %swift %s -emit-silgen -enable-private-discriminators | FileCheck %s
|
||||
// RUN: %swift -emit-module -o %t %S/Inputs/mangling_private_helper.swift -enable-private-discriminators
|
||||
// RUN: %swift -emit-silgen %S/Inputs/mangling_private_helper.swift -enable-private-discriminators | FileCheck %s -check-prefix=CHECK-BASE
|
||||
|
||||
// RUN: %swift %s -I %t -emit-silgen -enable-private-discriminators | FileCheck %s
|
||||
|
||||
// RUN: cp %s %t
|
||||
// RUN: %swift %t/mangling_private.swift -emit-silgen -enable-private-discriminators | FileCheck %s
|
||||
// RUN: %swift %t/mangling_private.swift -I %t -emit-silgen -enable-private-discriminators | FileCheck %s
|
||||
|
||||
// RUN: cp %s %t/other_name.swift
|
||||
// RUN: %swift %t/other_name.swift -emit-silgen -enable-private-discriminators -module-name mangling_private | FileCheck %s -check-prefix=OTHER-NAME
|
||||
// RUN: %swift %t/other_name.swift -I %t -emit-silgen -enable-private-discriminators -module-name mangling_private | FileCheck %s -check-prefix=OTHER-NAME
|
||||
|
||||
import mangling_private_helper
|
||||
|
||||
// CHECK-LABEL: sil @_TF16mangling_privateP33_713AFCDB29B710C2AB6F4DF7C1C8FEC911privateFuncFT_Si
|
||||
// OTHER-NAME-LABEL: sil @_TF16mangling_privateP33_AD9C6D430861F1E1D66B54DBCA7CC94B11privateFuncFT_Si
|
||||
@@ -49,3 +54,13 @@ extension PrivateStruct {
|
||||
private func extPrivateMethod() {}
|
||||
}
|
||||
|
||||
|
||||
// CHECK-LABEL: sil_vtable Sub {
|
||||
class Sub : Base {
|
||||
// CHECK-BASE: #Base.privateMethod!1: _TFC23mangling_private_helper4BaseP33_4EEA0BDF28CD79DFD969F8CFAF130D3813privateMethodfS0_FT_T_
|
||||
// CHECK-DAG: #Base.privateMethod!1: _TFC23mangling_private_helper4BaseP33_4EEA0BDF28CD79DFD969F8CFAF130D3813privateMethodfS0_FT_T_
|
||||
|
||||
// CHECK-DAG: #Sub.subMethod!1: _TFC16mangling_private3SubP33_713AFCDB29B710C2AB6F4DF7C1C8FEC99subMethodfS0_FT_T_
|
||||
private func subMethod() {}
|
||||
} // CHECK: {{^[}]$}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user