[Serialization] Preserve private discriminators through serialization.

Part of rdar://problem/17632175

Swift SVN r21611
This commit is contained in:
Jordan Rose
2014-08-30 17:27:02 +00:00
parent fcfd44c756
commit 1b51b60e72
8 changed files with 94 additions and 12 deletions

View File

@@ -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)

View File

@@ -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>;

View File

@@ -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<

View File

@@ -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(

View File

@@ -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;
}

View File

@@ -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>();

View 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() {}
}

View File

@@ -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: {{^[}]$}}