SILGen: Allow extensions to define designated initializers of generic types

Previously, if a generic type had a stored property with
a generic type and an initializer expression, we would
emit the expression directly in the body of each designated
initializer.

This is a problem if the designated initializer is defined
within an extension (even in the same source file), because
extensions have a different set of generic parameters and
archetypes.

Also, we've had bugs in the past where emitting an
expression multiple times didn't work properly. While these
might currently all be fixed, this is a tricky case to test
and it would be best to avoid it.

Fix both problems by emitting the initializer expression
inside its own function at the SIL level, and call the
initializer function from each designated initializer.

I'm using the existing 'variable initializer' mangling for this;
it doesn't seem to be used for anything else right now.

Currently, the default memberwise initializer does not use
this, because the machinery for emitting it is somewhat
duplicated and separate from the initializer expressions in
user-defined constructors. I'll clean this up in an upcoming
patch.

Fixes <https://bugs.swift.org/browse/SR-488>.
This commit is contained in:
Slava Pestov
2016-08-02 01:54:20 -04:00
parent f0b2598028
commit 75bd88968b
22 changed files with 284 additions and 59 deletions

View File

@@ -152,8 +152,11 @@ SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
"can only create ivar initializer/destroyer SILDeclRef for class");
naturalUncurryLevel = 1;
} else if (auto *var = dyn_cast<VarDecl>(vd)) {
assert((kind == Kind::GlobalAccessor || kind == Kind::GlobalGetter) &&
"can only create GlobalAccessor or GlobalGetter SILDeclRef for var");
assert((kind == Kind::GlobalAccessor ||
kind == Kind::GlobalGetter ||
kind == Kind::StoredPropertyInitializer) &&
"can only create GlobalAccessor, GlobalGetter or "
"StoredPropertyInitializer SILDeclRef for var");
naturalUncurryLevel = 0;
assert(!var->getDeclContext()->isLocalContext() &&
@@ -316,9 +319,14 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
// Enum constructors are essentially the same as thunks, they are
// emitted by need and have shared linkage.
if (kind == Kind::EnumElement)
if (isEnumElement())
return SILLinkage::Shared;
// Stored property initializers have hidden linkage, since they are
// not meant to be used from outside of their module.
if (isStoredPropertyInitializer())
return SILLinkage::Hidden;
// Declarations imported from Clang modules have shared linkage.
const SILLinkage ClangLinkage = SILLinkage::Shared;
@@ -353,6 +361,9 @@ bool SILDeclRef::isTransparent() const {
if (isEnumElement())
return true;
if (isStoredPropertyInitializer())
return true;
if (hasAutoClosureExpr())
return true;
@@ -576,12 +587,18 @@ static std::string mangleConstant(SILDeclRef c, StringRef prefix) {
mangler.mangleGlobalGetterEntity(c.getDecl());
return mangler.finalize();
// entity ::= context 'e' index // default arg generator
// entity ::= context 'e' index // default arg generator
case SILDeclRef::Kind::DefaultArgGenerator:
mangler.append(introducer);
mangler.mangleDefaultArgumentEntity(cast<AbstractFunctionDecl>(c.getDecl()),
c.defaultArgIndex);
return mangler.finalize();
// entity ::= 'I' declaration 'i' // stored property initializer
case SILDeclRef::Kind::StoredPropertyInitializer:
mangler.append(introducer);
mangler.mangleInitializerEntity(cast<VarDecl>(c.getDecl()));
return mangler.finalize();
}
llvm_unreachable("bad entity kind!");