mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -1852,6 +1852,9 @@ public:
|
||||
InitCheckedAndRemoved.setInt(
|
||||
InitCheckedAndRemoved.getInt() | Flags::Checked);
|
||||
}
|
||||
|
||||
// Return the first variable initialized by this pattern.
|
||||
VarDecl *getAnchoringVarDecl() const;
|
||||
};
|
||||
|
||||
/// \brief This decl contains a pattern and optional initializer for a set
|
||||
|
||||
@@ -117,6 +117,10 @@ struct SILDeclRef {
|
||||
/// References the generator for a default argument of a function.
|
||||
DefaultArgGenerator,
|
||||
|
||||
/// References the initializer expression for a stored property
|
||||
/// of a nominal type.
|
||||
StoredPropertyInitializer,
|
||||
|
||||
/// References the ivar initializer for the ClassDecl in loc.
|
||||
///
|
||||
/// Only classes that are allocated using Objective-C's allocation
|
||||
@@ -261,6 +265,11 @@ struct SILDeclRef {
|
||||
bool isDefaultArgGenerator() const {
|
||||
return kind == Kind::DefaultArgGenerator;
|
||||
}
|
||||
/// True if the SILDeclRef references the initializer for a stored property
|
||||
/// of a nominal type.
|
||||
bool isStoredPropertyInitializer() const {
|
||||
return kind == Kind::StoredPropertyInitializer;
|
||||
}
|
||||
|
||||
/// \brief True if the function should be treated as transparent.
|
||||
bool isTransparent() const;
|
||||
|
||||
@@ -949,6 +949,13 @@ void PatternBindingEntry::setInit(Expr *E) {
|
||||
}
|
||||
}
|
||||
|
||||
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
|
||||
SmallVector<VarDecl *, 8> variables;
|
||||
getPattern()->collectVariables(variables);
|
||||
assert(variables.size() > 0);
|
||||
return variables[0];
|
||||
}
|
||||
|
||||
SourceRange PatternBindingDecl::getSourceRange() const {
|
||||
SourceLoc startLoc = getStartLoc();
|
||||
|
||||
|
||||
@@ -512,6 +512,7 @@ namespace {
|
||||
Selector(SILDeclRef ref) {
|
||||
switch (ref.kind) {
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
case SILDeclRef::Kind::EnumElement:
|
||||
case SILDeclRef::Kind::GlobalAccessor:
|
||||
case SILDeclRef::Kind::GlobalGetter:
|
||||
|
||||
@@ -1053,6 +1053,12 @@ bool SILParser::parseSILDeclRef(SILDeclRef &Result,
|
||||
} else if (!ParseState && Id.str() == "ivarinitializer") {
|
||||
Kind = SILDeclRef::Kind::IVarInitializer;
|
||||
ParseState = 1;
|
||||
} else if (!ParseState && Id.str() == "defaultarg") {
|
||||
Kind = SILDeclRef::Kind::IVarInitializer;
|
||||
ParseState = 1;
|
||||
} else if (!ParseState && Id.str() == "propertyinit") {
|
||||
Kind = SILDeclRef::Kind::StoredPropertyInitializer;
|
||||
ParseState = 1;
|
||||
} else if (Id.str() == "foreign") {
|
||||
IsObjC = true;
|
||||
break;
|
||||
|
||||
@@ -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!");
|
||||
|
||||
@@ -1003,6 +1003,7 @@ static CanSILFunctionType getNativeSILFunctionType(SILModule &M,
|
||||
case SILDeclRef::Kind::GlobalAccessor:
|
||||
case SILDeclRef::Kind::GlobalGetter:
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
case SILDeclRef::Kind::IVarInitializer:
|
||||
case SILDeclRef::Kind::IVarDestroyer:
|
||||
case SILDeclRef::Kind::EnumElement:
|
||||
@@ -1472,6 +1473,7 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
|
||||
case SILDeclRef::Kind::GlobalGetter:
|
||||
case SILDeclRef::Kind::IVarDestroyer:
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
return SelectorFamily::None;
|
||||
}
|
||||
}
|
||||
@@ -1653,6 +1655,7 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) {
|
||||
case SILDeclRef::Kind::GlobalAccessor:
|
||||
case SILDeclRef::Kind::GlobalGetter:
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
return SILFunctionTypeRepresentation::Thin;
|
||||
|
||||
case SILDeclRef::Kind::Func:
|
||||
@@ -2319,6 +2322,7 @@ static AbstractFunctionDecl *getBridgedFunction(SILDeclRef declRef) {
|
||||
case SILDeclRef::Kind::GlobalAccessor:
|
||||
case SILDeclRef::Kind::GlobalGetter:
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
case SILDeclRef::Kind::IVarInitializer:
|
||||
case SILDeclRef::Kind::IVarDestroyer:
|
||||
return nullptr;
|
||||
|
||||
@@ -322,6 +322,9 @@ void SILDeclRef::print(raw_ostream &OS) const {
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
OS << "!defaultarg" << "." << defaultArgIndex;
|
||||
break;
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
OS << "!propertyinit";
|
||||
break;
|
||||
}
|
||||
if (uncurryLevel != 0)
|
||||
OS << (isDot ? '.' : '!') << uncurryLevel;
|
||||
|
||||
@@ -1671,6 +1671,27 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
|
||||
return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
|
||||
}
|
||||
|
||||
/// Get the type of a stored property initializer, () -> T.
|
||||
static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
|
||||
TypeConverter &TC,
|
||||
VarDecl *VD,
|
||||
ASTContext &context) {
|
||||
auto *DC = VD->getDeclContext();
|
||||
CanType resultTy =
|
||||
ArchetypeBuilder::mapTypeOutOfContext(
|
||||
DC, VD->getParentInitializer()->getType())
|
||||
->getCanonicalType();
|
||||
GenericSignature *sig = DC->getGenericSignatureOfContext();
|
||||
|
||||
if (sig)
|
||||
return CanGenericFunctionType::get(sig->getCanonicalSignature(),
|
||||
TupleType::getEmpty(context),
|
||||
resultTy,
|
||||
GenericFunctionType::ExtInfo());
|
||||
|
||||
return CanFunctionType::get(TupleType::getEmpty(context), resultTy);
|
||||
}
|
||||
|
||||
/// Get the type of a destructor function.
|
||||
static CanAnyFunctionType getDestructorInterfaceType(DestructorDecl *dd,
|
||||
bool isDeallocating,
|
||||
@@ -1868,8 +1889,12 @@ CanAnyFunctionType TypeConverter::makeConstantInterfaceType(SILDeclRef c) {
|
||||
}
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
return getDefaultArgGeneratorInterfaceType(*this,
|
||||
cast<AbstractFunctionDecl>(vd),
|
||||
c.defaultArgIndex, Context);
|
||||
cast<AbstractFunctionDecl>(vd),
|
||||
c.defaultArgIndex, Context);
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
return getStoredPropertyInitializerInterfaceType(*this,
|
||||
cast<VarDecl>(vd),
|
||||
Context);
|
||||
case SILDeclRef::Kind::IVarInitializer:
|
||||
return getIVarInitDestroyerInterfaceType(cast<ClassDecl>(vd),
|
||||
c.isForeign, Context, false);
|
||||
@@ -1926,6 +1951,12 @@ TypeConverter::getConstantContextGenericParams(SILDeclRef c) {
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
// Use the context generic parameters of the original declaration.
|
||||
return getConstantContextGenericParams(SILDeclRef(c.getDecl()));
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
// Use the context generic parameters of the containing type.
|
||||
return {
|
||||
c.getDecl()->getDeclContext()->getGenericParamsOfContext(),
|
||||
nullptr,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -877,6 +877,21 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, Expr *arg) {
|
||||
});
|
||||
}
|
||||
|
||||
void SILGenModule::
|
||||
emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
|
||||
const PatternBindingEntry &pbdEntry = pbd->getPatternList()[i];
|
||||
auto *var = pbdEntry.getAnchoringVarDecl();
|
||||
auto *init = pbdEntry.getInit();
|
||||
|
||||
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
|
||||
emitOrDelayFunction(*this, constant, [this,constant,init](SILFunction *f) {
|
||||
preEmitFunction(constant, init, f, init);
|
||||
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
|
||||
SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
|
||||
postEmitFunction(constant, f);
|
||||
});
|
||||
}
|
||||
|
||||
SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName,
|
||||
PatternBindingDecl *binding,
|
||||
unsigned pbdEntry) {
|
||||
|
||||
@@ -252,7 +252,10 @@ public:
|
||||
|
||||
/// Emits the default argument generator with the given expression.
|
||||
void emitDefaultArgGenerator(SILDeclRef constant, Expr *arg);
|
||||
|
||||
|
||||
/// Emits the stored property initializer for the given pattern.
|
||||
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
|
||||
|
||||
/// Emits the default argument generator for the given function.
|
||||
void emitDefaultArgGenerators(SILDeclRef::Loc decl,
|
||||
ArrayRef<ParameterList*> paramLists);
|
||||
|
||||
@@ -253,9 +253,9 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
|
||||
|
||||
// If this is not a delegating constructor, emit member initializers.
|
||||
if (!isDelegating) {
|
||||
auto nominal = ctor->getDeclContext()
|
||||
->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||
emitMemberInitializers(selfDecl, nominal);
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto *nominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||
emitMemberInitializers(dc, selfDecl, nominal);
|
||||
}
|
||||
|
||||
emitProfilerIncrement(ctor->getBody());
|
||||
@@ -526,7 +526,8 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
// TODO: If we could require Objective-C classes to have an attribute to get
|
||||
// this behavior, we could avoid runtime overhead here.
|
||||
VarDecl *selfDecl = ctor->getImplicitSelfDecl();
|
||||
auto selfClassDecl = ctor->getDeclContext()->getAsClassOrClassExtensionContext();
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto selfClassDecl = dc->getAsClassOrClassExtensionContext();
|
||||
bool NeedsBoxForSelf = isDelegating ||
|
||||
(selfClassDecl->hasSuperclass() && !ctor->hasStubImplementation());
|
||||
bool usesObjCAllocator = Lowering::usesObjCAllocator(selfClassDecl);
|
||||
@@ -642,7 +643,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
// Note that 'self' has been fully initialized at this point.
|
||||
} else {
|
||||
// Emit the member initializers.
|
||||
emitMemberInitializers(selfDecl, selfClassDecl);
|
||||
emitMemberInitializers(dc, selfDecl, selfClassDecl);
|
||||
}
|
||||
|
||||
emitProfilerIncrement(ctor->getBody());
|
||||
@@ -841,7 +842,19 @@ static SILValue getBehaviorSetterFn(SILGenFunction &gen, VarDecl *behaviorVar) {
|
||||
return gen.B.createFunctionRef(behaviorVar, setFn);
|
||||
}
|
||||
|
||||
void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,
|
||||
static Type getInitializationTypeInContext(
|
||||
DeclContext *fromDC, DeclContext *toDC,
|
||||
Expr *init) {
|
||||
auto interfaceType =
|
||||
ArchetypeBuilder::mapTypeOutOfContext(fromDC, init->getType());
|
||||
auto resultType =
|
||||
ArchetypeBuilder::mapTypeIntoContext(toDC, interfaceType);
|
||||
|
||||
return resultType;
|
||||
}
|
||||
|
||||
void SILGenFunction::emitMemberInitializers(DeclContext *dc,
|
||||
VarDecl *selfDecl,
|
||||
NominalTypeDecl *nominal) {
|
||||
for (auto member : nominal->getMembers()) {
|
||||
// Find instance pattern binding declarations that have initializers.
|
||||
@@ -854,7 +867,27 @@ void SILGenFunction::emitMemberInitializers(VarDecl *selfDecl,
|
||||
|
||||
// Cleanup after this initialization.
|
||||
FullExpr scope(Cleanups, entry.getPattern());
|
||||
emitMemberInit(*this, selfDecl, entry.getPattern(), emitRValue(init));
|
||||
|
||||
// Get the substitutions for the constructor context.
|
||||
ArrayRef<Substitution> subs;
|
||||
auto *genericParams = dc->getGenericParamsOfContext();
|
||||
if (genericParams)
|
||||
subs = genericParams->getForwardingSubstitutions(getASTContext());
|
||||
|
||||
// Get the type of the initialization result, in terms
|
||||
// of the constructor context's archetypes.
|
||||
CanType resultType = getInitializationTypeInContext(
|
||||
pbd->getDeclContext(), dc, init)->getCanonicalType();
|
||||
AbstractionPattern origResultType(resultType);
|
||||
|
||||
// FIXME: Can emitMemberInit() share code with
|
||||
// InitializationForPattern in SILGenDecl.cpp?
|
||||
RValue result = emitApplyOfStoredPropertyInitializer(
|
||||
init, entry, subs,
|
||||
resultType, origResultType,
|
||||
SGFContext());
|
||||
|
||||
emitMemberInit(*this, selfDecl, entry.getPattern(), std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,7 +946,7 @@ void SILGenFunction::emitIVarInitializer(SILDeclRef ivarInitializer) {
|
||||
prepareEpilog(TupleType::getEmpty(getASTContext()), false, cleanupLoc);
|
||||
|
||||
// Emit the initializers.
|
||||
emitMemberInitializers(cd->getDestructor()->getImplicitSelfDecl(), cd);
|
||||
emitMemberInitializers(cd, selfDecl, cd);
|
||||
|
||||
// Return 'self'.
|
||||
B.createReturn(loc, selfArg);
|
||||
|
||||
@@ -1724,6 +1724,29 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc,
|
||||
ApplyOptions::None, None, None, C);
|
||||
}
|
||||
|
||||
RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
|
||||
SILLocation loc,
|
||||
const PatternBindingEntry &entry,
|
||||
ArrayRef<Substitution> subs,
|
||||
CanType resultType,
|
||||
AbstractionPattern origResultType,
|
||||
SGFContext C) {
|
||||
|
||||
VarDecl *var = entry.getAnchoringVarDecl();
|
||||
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
|
||||
auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc, constant));
|
||||
auto fnType = fnRef.getType().castTo<SILFunctionType>();
|
||||
|
||||
auto substFnType = fnType->substGenericArgs(SGM.M, SGM.M.getSwiftModule(),
|
||||
subs);
|
||||
|
||||
return emitApply(loc, fnRef, subs, {},
|
||||
substFnType,
|
||||
origResultType,
|
||||
resultType,
|
||||
ApplyOptions::None, None, None, C);
|
||||
}
|
||||
|
||||
static void emitTupleShuffleExprInto(RValueEmitter &emitter,
|
||||
TupleShuffleExpr *E,
|
||||
Initialization *outerTupleInit) {
|
||||
|
||||
@@ -120,6 +120,8 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
|
||||
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
|
||||
case SILDeclRef::Kind::DefaultArgGenerator:
|
||||
return getMagicFunctionName(cast<AbstractFunctionDecl>(ref.getDecl()));
|
||||
case SILDeclRef::Kind::StoredPropertyInitializer:
|
||||
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
|
||||
case SILDeclRef::Kind::IVarInitializer:
|
||||
return getMagicFunctionName(cast<ClassDecl>(ref.getDecl()));
|
||||
case SILDeclRef::Kind::IVarDestroyer:
|
||||
|
||||
@@ -572,9 +572,11 @@ public:
|
||||
/// Generates code to initialize instance variables from their
|
||||
/// initializers.
|
||||
///
|
||||
/// \param dc The DeclContext containing the current function.
|
||||
/// \param selfDecl The 'self' declaration within the current function.
|
||||
/// \param nominal The type whose members are being initialized.
|
||||
void emitMemberInitializers(VarDecl *selfDecl, NominalTypeDecl *nominal);
|
||||
void emitMemberInitializers(DeclContext *dc, VarDecl *selfDecl,
|
||||
NominalTypeDecl *nominal);
|
||||
|
||||
/// Emit a method that initializes the ivars of a class.
|
||||
void emitIVarInitializer(SILDeclRef ivarInitializer);
|
||||
@@ -597,7 +599,7 @@ public:
|
||||
/// Generates a thunk from a native function to the conventions.
|
||||
void emitNativeToForeignThunk(SILDeclRef thunk);
|
||||
|
||||
// Generate a nullary function that returns the given value.
|
||||
/// Generate a nullary function that returns the given value.
|
||||
void emitGeneratorFunction(SILDeclRef function, Expr *value);
|
||||
|
||||
/// Generate an ObjC-compatible destructor (-dealloc).
|
||||
@@ -1231,6 +1233,14 @@ public:
|
||||
AbstractionPattern origResultType,
|
||||
SGFContext C = SGFContext());
|
||||
|
||||
RValue emitApplyOfStoredPropertyInitializer(
|
||||
SILLocation loc,
|
||||
const PatternBindingEntry &entry,
|
||||
ArrayRef<Substitution> subs,
|
||||
CanType resultType,
|
||||
AbstractionPattern origResultType,
|
||||
SGFContext C);
|
||||
|
||||
/// A convenience method for emitApply that just handles monomorphic
|
||||
/// applications.
|
||||
RValue emitMonomorphicApply(SILLocation loc,
|
||||
|
||||
@@ -379,12 +379,15 @@ public:
|
||||
void visitEnumElementDecl(EnumElementDecl *ued) {}
|
||||
|
||||
void visitPatternBindingDecl(PatternBindingDecl *pd) {
|
||||
// Emit initializers for static variables.
|
||||
if (!pd->isStatic()) return;
|
||||
|
||||
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i)
|
||||
if (pd->getInit(i))
|
||||
SGM.emitGlobalInitialization(pd, i);
|
||||
// Emit initializers.
|
||||
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
|
||||
if (pd->getInit(i)) {
|
||||
if (pd->isStatic())
|
||||
SGM.emitGlobalInitialization(pd, i);
|
||||
else
|
||||
SGM.emitStoredPropertyInitialization(pd, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitVarDecl(VarDecl *vd) {
|
||||
@@ -472,17 +475,19 @@ public:
|
||||
|
||||
void visitPatternBindingDecl(PatternBindingDecl *pd) {
|
||||
// Emit initializers for static variables.
|
||||
if (!pd->isStatic()) return;
|
||||
|
||||
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i)
|
||||
if (pd->getInit(i))
|
||||
for (unsigned i = 0, e = pd->getNumPatternEntries(); i != e; ++i) {
|
||||
if (pd->getInit(i)) {
|
||||
assert(pd->isStatic() && "stored property in extension?!");
|
||||
SGM.emitGlobalInitialization(pd, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitVarDecl(VarDecl *vd) {
|
||||
if (vd->hasBehavior())
|
||||
SGM.emitPropertyBehavior(vd);
|
||||
if (vd->isStatic() && vd->hasStorage()) {
|
||||
if (vd->hasStorage()) {
|
||||
assert(vd->isStatic() && "stored property in extension?!");
|
||||
ExtensionDecl *ext = cast<ExtensionDecl>(vd->getDeclContext());
|
||||
NominalTypeDecl *theType = ext->getExtendedType()->getAnyNominal();
|
||||
return emitTypeMemberGlobalVariable(SGM, ext->getGenericParams(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s | FileCheck %s
|
||||
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -primary-file %s | FileCheck %s
|
||||
|
||||
struct B {
|
||||
var i : Int, j : Float
|
||||
@@ -13,17 +13,27 @@ struct C {
|
||||
struct D {
|
||||
var (i, j) : (Int, Double) = (2, 3.5)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden [transparent] @_TIvV19default_constructor1D1iSii : $@convention(thin) () -> (Int, Double)
|
||||
// CHECK: [[FN:%.*]] = function_ref @_TFSiCfT22_builtinIntegerLiteralBi2048__Si : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Int.Type
|
||||
// CHECK-NEXT: [[VALUE:%.*]] = integer_literal $Builtin.Int2048, 2
|
||||
// CHECK-NEXT: [[LEFT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
|
||||
// CHECK: [[FN:%.*]] = function_ref @_TFSdCfT20_builtinFloatLiteralBf80__Sd : $@convention(method) (Builtin.FPIEEE80, @thin Double.Type) -> Double
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Double.Type
|
||||
// CHECK-NEXT: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0x4000E000000000000000
|
||||
// CHECK-NEXT: [[RIGHT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Double.Type) -> Double
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Double)
|
||||
// CHECK-NEXT: return [[RESULT]] : $(Int, Double)
|
||||
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFV19default_constructor1DC{{.*}} : $@convention(method) (@thin D.Type) -> D
|
||||
// CHECK: [[THISBOX:%[0-9]+]] = alloc_box $D
|
||||
// CHECK: [[THIS:%[0-9]+]] = mark_uninit
|
||||
// CHECK: [[INTCONV:%[0-9]+]] = function_ref @_TFSiC
|
||||
// CHECK: [[INTMETA:%[0-9]+]] = metatype $@thin Int.Type
|
||||
// CHECK: [[INTLIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 2
|
||||
// CHECK: [[INTVAL:%[0-9]+]] = apply [[INTCONV]]([[INTLIT]], [[INTMETA]])
|
||||
// CHECK: [[FLOATCONV:%[0-9]+]] = function_ref @_TFSdC
|
||||
// CHECK: [[FLOATMETA:%[0-9]+]] = metatype $@thin Double.Type
|
||||
// CHECK: [[FLOATLIT:%[0-9]+]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x400C000000000000|0x4000E000000000000000}}
|
||||
// CHECK: [[FLOATVAL:%[0-9]+]] = apply [[FLOATCONV]]([[FLOATLIT]], [[FLOATMETA]])
|
||||
// CHECK: [[INIT:%[0-9]+]] = function_ref @_TIvV19default_constructor1D1iSii
|
||||
// CHECK: [[RESULT:%[0-9]+]] = apply [[INIT]]()
|
||||
// CHECK: [[INTVAL:%[0-9]+]] = tuple_extract [[RESULT]] : $(Int, Double), 0
|
||||
// CHECK: [[FLOATVAL:%[0-9]+]] = tuple_extract [[RESULT]] : $(Int, Double), 1
|
||||
// CHECK: [[IADDR:%[0-9]+]] = struct_element_addr [[THIS]] : $*D, #D.i
|
||||
// CHECK: assign [[INTVAL]] to [[IADDR]]
|
||||
// CHECK: [[JADDR:%[0-9]+]] = struct_element_addr [[THIS]] : $*D, #D.j
|
||||
@@ -33,14 +43,19 @@ class E {
|
||||
var i = Int64()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden [transparent] @_TIvC19default_constructor1E1iVs5Int64i : $@convention(thin) () -> Int64
|
||||
// CHECK: [[FN:%.*]] = function_ref @_TFVs5Int64CfT_S_ : $@convention(method) (@thin Int64.Type) -> Int64
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Int64.Type
|
||||
// CHECK-NEXT: [[VALUE:%.*]] = apply [[FN]]([[METATYPE]]) : $@convention(method) (@thin Int64.Type) -> Int64
|
||||
// CHECK-NEXT: return [[VALUE]] : $Int64
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFC19default_constructor1Ec{{.*}} : $@convention(method) (@owned E) -> @owned E
|
||||
// CHECK: bb0([[SELFIN:%[0-9]+]] : $E)
|
||||
// CHECK: [[SELF:%[0-9]+]] = mark_uninitialized
|
||||
// CHECK: [[INT64_CTOR:%[0-9]+]] = function_ref @_TFVs5Int64C{{.*}} : $@convention(method) (@thin Int64.Type) -> Int64
|
||||
// CHECK-NEXT: [[INT64:%[0-9]+]] = metatype $@thin Int64.Type
|
||||
// CHECK-NEXT: [[ZERO:%[0-9]+]] = apply [[INT64_CTOR]]([[INT64]]) : $@convention(method) (@thin Int64.Type) -> Int64
|
||||
// CHECK: [[INIT:%[0-9]+]] = function_ref @_TIvC19default_constructor1E1iVs5Int64i : $@convention(thin) () -> Int64
|
||||
// CHECK-NEXT: [[VALUE:%[0-9]+]] = apply [[INIT]]() : $@convention(thin) () -> Int64
|
||||
// CHECK-NEXT: [[IREF:%[0-9]+]] = ref_element_addr [[SELF]] : $E, #E.i
|
||||
// CHECK-NEXT: assign [[ZERO]] to [[IREF]] : $*Int64
|
||||
// CHECK-NEXT: assign [[VALUE]] to [[IREF]] : $*Int64
|
||||
// CHECK-NEXT: return [[SELF]] : $E
|
||||
|
||||
class F : E { }
|
||||
@@ -76,12 +91,3 @@ struct G {
|
||||
// CHECK-LABEL: default_constructor.G.init (bar : Swift.Optional<Swift.Int32>)
|
||||
// CHECK-NEXT: sil hidden @_TFV19default_constructor1GC
|
||||
// CHECK-NOT: default_constructor.G.init ()
|
||||
|
||||
func useImplicitDecls() {
|
||||
_ = B(i: 0, j: 0, c: C())
|
||||
_ = D()
|
||||
_ = D(i: 0, j: 0)
|
||||
_ = E()
|
||||
_ = F()
|
||||
_ = G(bar: 0)
|
||||
}
|
||||
|
||||
@@ -39,3 +39,46 @@ func extensionMethodCurrying(_ x: Foo) {
|
||||
|
||||
// CHECK-LABEL: sil shared [thunk] @_TFC10extensions3Foo4zang
|
||||
// CHECK: function_ref @_TFC10extensions3Foo4zang
|
||||
|
||||
// Extensions of generic types with stored property initializers
|
||||
|
||||
// CHECK-LABEL: sil hidden [transparent] @_TIvV10extensions3Box1tGSqx_i : $@convention(thin) <T> () -> @out Optional<T>
|
||||
// CHECK: bb0(%0 : $*Optional<T>):
|
||||
// CHECK: [[FN:%.*]] = function_ref @_TFSqCfT10nilLiteralT__GSqx_ : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Optional<T>.Type
|
||||
// CHECK-NEXT: apply [[FN]]<T>(%0, [[METATYPE]]) : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
|
||||
// CHECK-NEXT: return [[RESULT]] : $()
|
||||
|
||||
struct Box<T> {
|
||||
let t: T? = nil
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFV10extensions3BoxCfT1tx_GS0_x_ : $@convention(method) <T> (@in T, @thin Box<T>.Type) -> @out Box<T>
|
||||
// CHECK: [[SELF_BOX:%.*]] = alloc_box $Box<T>
|
||||
// CHECK-NEXT: [[SELF_ADDR:%.*]] = project_box [[SELF_BOX]] : $@box Box<T>
|
||||
// CHECK: [[SELF_PTR:%.*]] = mark_uninitialized [rootself] [[SELF_ADDR]] : $*Box<T>
|
||||
// CHECK: [[INIT:%.*]] = function_ref @_TIvV10extensions3Box1tGSqx_i : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional<T>
|
||||
// CHECK-NEXT: apply [[INIT]]<T>([[RESULT]]) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
|
||||
// CHECK-NEXT: [[T_ADDR:%.*]] = struct_element_addr [[SELF_PTR]] : $*Box<T>, #Box.t
|
||||
// CHECK-NEXT: copy_addr [take] [[RESULT]] to [[T_ADDR]] : $*Optional<T>
|
||||
// CHECK-NEXT: dealloc_stack [[RESULT]] : $*Optional<T>
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional<T>
|
||||
// CHECK-NEXT: [[RESULT_ADDR:%.*]] = init_enum_data_addr [[RESULT]] : $*Optional<T>, #Optional.some!enumelt.1
|
||||
// CHECK-NEXT: copy_addr %1 to [initialization] %14 : $*T
|
||||
// CHECK-NEXT: inject_enum_addr [[RESULT]] : $*Optional<T>, #Optional.some!enumelt.1
|
||||
// CHECK-NEXT: [[T_ADDR:%.*]] = struct_element_addr [[SELF_PTR]] : $*Box<T>, #Box.t
|
||||
// CHECK-NEXT: copy_addr [take] [[RESULT]] to [[T_ADDR:%.*]] : $*Optional<T>
|
||||
// CHECK-NEXT: dealloc_stack [[RESULT]] : $*Optional<T>
|
||||
// CHECK-NEXT: copy_addr [[SELF_PTR]] to [initialization] %0 : $*Box<T>
|
||||
// CHECK-NEXT: destroy_addr %1 : $*T
|
||||
// CHECK-NEXT: strong_release [[SELF_BOX]] : $@box Box<T>
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
|
||||
// CHECK-NEXT: return [[RESULT]] : $()
|
||||
|
||||
extension Box {
|
||||
init(t: T) {
|
||||
self.t = t
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,9 +406,8 @@ class Foo<T> {
|
||||
// CHECK: [[THIS:%[0-9]+]] = mark_uninitialized
|
||||
|
||||
// initialization for y
|
||||
// CHECK: [[INTCTOR:%[0-9]+]] = function_ref @_TFSiC{{.*}} : $@convention(method) (@thin Int.Type) -> Int
|
||||
// CHECK: [[INTMETA:%[0-9]+]] = metatype $@thin Int.Type
|
||||
// CHECK: [[INTVAL:%[0-9]+]] = apply [[INTCTOR]]([[INTMETA]])
|
||||
// CHECK: [[Y_INIT:%[0-9]+]] = function_ref @_TIvC8lifetime3Foo1yTSiCS_3Ref_i : $@convention(thin) <τ_0_0> () -> (Int, @owned Ref)
|
||||
// CHECK: [[Y_VALUE:%[0-9]+]] = apply [[Y_INIT]]<T>()
|
||||
|
||||
x = bar()
|
||||
// CHECK: function_ref @_TF8lifetime3barFT_Si : $@convention(thin) () -> Int
|
||||
|
||||
@@ -11,6 +11,12 @@ func onDestruct() { }
|
||||
class SwiftGizmo : Gizmo {
|
||||
var x = X()
|
||||
|
||||
// CHECK-LABEL: sil hidden [transparent] @_TIvC12objc_dealloc10SwiftGizmo1xCS_1Xi : $@convention(thin) () -> @owned X
|
||||
// CHECK: [[FN:%.*]] = function_ref @_TFC12objc_dealloc1XCfT_S0_ : $@convention(method) (@thick X.Type) -> @owned X
|
||||
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick X.Type
|
||||
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[METATYPE]]) : $@convention(method) (@thick X.Type) -> @owned X
|
||||
// CHECK-NEXT: return [[RESULT]] : $X
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFC12objc_dealloc10SwiftGizmoc
|
||||
// CHECK: bb0([[SELF_PARAM:%[0-9]+]] : $SwiftGizmo):
|
||||
override init() {
|
||||
@@ -55,9 +61,8 @@ class SwiftGizmo : Gizmo {
|
||||
// CHECK: bb0([[SELF_PARAM:%[0-9]+]] : $SwiftGizmo):
|
||||
// CHECK-NEXT: debug_value [[SELF_PARAM]] : $SwiftGizmo, let, name "self"
|
||||
// CHECK-NEXT: [[SELF:%[0-9]+]] = mark_uninitialized [rootself] [[SELF_PARAM]] : $SwiftGizmo
|
||||
// CHECK: [[XCTOR:%[0-9]+]] = function_ref @_TFC12objc_dealloc1XC
|
||||
// CHECK-NEXT: [[XMETA:%[0-9]+]] = metatype $@thick X.Type
|
||||
// CHECK-NEXT: [[XOBJ:%[0-9]+]] = apply [[XCTOR]]([[XMETA]]) : $@convention(method) (@thick X.Type) -> @owned X
|
||||
// CHECK: [[XINIT:%[0-9]+]] = function_ref @_TIvC12objc_dealloc10SwiftGizmo1xCS_1Xi
|
||||
// CHECK-NEXT: [[XOBJ:%[0-9]+]] = apply [[XINIT]]() : $@convention(thin) () -> @owned X
|
||||
// CHECK-NEXT: [[X:%[0-9]+]] = ref_element_addr [[SELF]] : $SwiftGizmo, #SwiftGizmo.x
|
||||
// CHECK-NEXT: assign [[XOBJ]] to [[X]] : $*X
|
||||
// CHECK-NEXT: return [[SELF]] : $SwiftGizmo
|
||||
|
||||
@@ -450,12 +450,12 @@ class DesignatedOverrides : Gizmo {
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFC11objc_thunks19DesignatedOverridesc{{.*}}
|
||||
// CHECK-NOT: return
|
||||
// CHECK: function_ref @_TFSiC{{.*}}
|
||||
// CHECK: function_ref @_TIvC11objc_thunks19DesignatedOverrides1iSii : $@convention(thin) () -> Int
|
||||
// CHECK: super_method [volatile] [[SELF:%[0-9]+]] : $DesignatedOverrides, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> () -> Gizmo! , $@convention(objc_method) (@owned Gizmo) -> @owned ImplicitlyUnwrappedOptional<Gizmo>
|
||||
// CHECK: return
|
||||
|
||||
// CHECK-LABEL: sil hidden @_TFC11objc_thunks19DesignatedOverridesc{{.*}}
|
||||
// CHECK: function_ref @_TFSiC{{.*}}
|
||||
// CHECK: function_ref @_TIvC11objc_thunks19DesignatedOverrides1iSii : $@convention(thin) () -> Int
|
||||
// CHECK: super_method [volatile] [[SELF:%[0-9]+]] : $DesignatedOverrides, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo! , $@convention(objc_method) (Int, @owned Gizmo) -> @owned ImplicitlyUnwrappedOptional<Gizmo>
|
||||
// CHECK: return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
|
||||
// RUN: not --crash %target-swift-frontend %s -emit-silgen
|
||||
// RUN: %target-swift-frontend %s -emit-silgen
|
||||
// Test case submitted to project by https://github.com/airspeedswift (airspeedswift)
|
||||
|
||||
struct S<T> {
|
||||
Reference in New Issue
Block a user