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

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

View File

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

View File

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

View File

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

View File

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

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!");

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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