Skip to content

Commit 3bb81e3

Browse files
committed
[SILGenConstructor] NFC: Extract initialization of individual fields into a method
This is a preliminary step in order to enable re-ordering of initializations when init accessors are involved.
1 parent b962cab commit 3bb81e3

File tree

2 files changed

+82
-63
lines changed

2 files changed

+82
-63
lines changed

lib/SILGen/SILGenConstructor.cpp

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,76 @@ void SILGenFunction::emitMemberInitializationViaInitAccessor(
15021502
B.createEndAccess(loc, selfRef.getValue(), /*aborted=*/false);
15031503
}
15041504

1505+
void SILGenFunction::emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
1506+
PatternBindingDecl *field,
1507+
SubstitutionMap substitutions) {
1508+
assert(!field->isStatic());
1509+
1510+
for (auto i : range(field->getNumPatternEntries())) {
1511+
auto init = field->getExecutableInit(i);
1512+
if (!init)
1513+
continue;
1514+
1515+
auto *varPattern = field->getPattern(i);
1516+
1517+
// Cleanup after this initialization.
1518+
FullExpr scope(Cleanups, varPattern);
1519+
1520+
// Get the type of the initialization result, in terms
1521+
// of the constructor context's archetypes.
1522+
auto resultType =
1523+
getInitializationTypeInContext(field->getDeclContext(), dc, varPattern);
1524+
AbstractionPattern origType = resultType.first;
1525+
CanType substType = resultType.second;
1526+
1527+
// Figure out what we're initializing.
1528+
auto memberInit = emitMemberInit(*this, selfDecl, varPattern);
1529+
1530+
// This whole conversion thing is about eliminating the
1531+
// paired orig-to-subst subst-to-orig conversions that
1532+
// will happen if the storage is at a different abstraction
1533+
// level than the constructor. When emitApply() is used
1534+
// to call the stored property initializer, it naturally
1535+
// wants to convert the result back to the most substituted
1536+
// abstraction level. To undo this, we use a converting
1537+
// initialization and rely on the peephole that optimizes
1538+
// out the redundant conversion.
1539+
SILType loweredResultTy;
1540+
SILType loweredSubstTy;
1541+
1542+
// A converting initialization isn't necessary if the member is
1543+
// a property wrapper. Though the initial value can have a
1544+
// reabstractable type, the result of the initialization is
1545+
// always the property wrapper type, which is never reabstractable.
1546+
bool needsConvertingInit = false;
1547+
auto *singleVar = varPattern->getSingleVar();
1548+
if (!(singleVar && singleVar->getOriginalWrappedProperty())) {
1549+
loweredResultTy = getLoweredType(origType, substType);
1550+
loweredSubstTy = getLoweredType(substType);
1551+
needsConvertingInit = loweredResultTy != loweredSubstTy;
1552+
}
1553+
1554+
if (needsConvertingInit) {
1555+
Conversion conversion =
1556+
Conversion::getSubstToOrig(origType, substType, loweredResultTy);
1557+
1558+
ConvertingInitialization convertingInit(conversion,
1559+
SGFContext(memberInit.get()));
1560+
1561+
emitAndStoreInitialValueInto(*this, varPattern, field, i, substitutions,
1562+
origType, substType, &convertingInit);
1563+
1564+
auto finalValue = convertingInit.finishEmission(
1565+
*this, varPattern, ManagedValue::forInContext());
1566+
if (!finalValue.isInContext())
1567+
finalValue.forwardInto(*this, varPattern, memberInit.get());
1568+
} else {
1569+
emitAndStoreInitialValueInto(*this, varPattern, field, i, substitutions,
1570+
origType, substType, memberInit.get());
1571+
}
1572+
}
1573+
}
1574+
15051575
void SILGenFunction::emitMemberInitializers(DeclContext *dc,
15061576
VarDecl *selfDecl,
15071577
NominalTypeDecl *nominal) {
@@ -1520,69 +1590,7 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
15201590
}
15211591
}
15221592

1523-
for (auto i : range(pbd->getNumPatternEntries())) {
1524-
auto init = pbd->getExecutableInit(i);
1525-
if (!init) continue;
1526-
1527-
auto *varPattern = pbd->getPattern(i);
1528-
1529-
// Cleanup after this initialization.
1530-
FullExpr scope(Cleanups, varPattern);
1531-
1532-
// Get the type of the initialization result, in terms
1533-
// of the constructor context's archetypes.
1534-
auto resultType = getInitializationTypeInContext(
1535-
pbd->getDeclContext(), dc, varPattern);
1536-
AbstractionPattern origType = resultType.first;
1537-
CanType substType = resultType.second;
1538-
1539-
// Figure out what we're initializing.
1540-
auto memberInit = emitMemberInit(*this, selfDecl, varPattern);
1541-
1542-
// This whole conversion thing is about eliminating the
1543-
// paired orig-to-subst subst-to-orig conversions that
1544-
// will happen if the storage is at a different abstraction
1545-
// level than the constructor. When emitApply() is used
1546-
// to call the stored property initializer, it naturally
1547-
// wants to convert the result back to the most substituted
1548-
// abstraction level. To undo this, we use a converting
1549-
// initialization and rely on the peephole that optimizes
1550-
// out the redundant conversion.
1551-
SILType loweredResultTy;
1552-
SILType loweredSubstTy;
1553-
1554-
// A converting initialization isn't necessary if the member is
1555-
// a property wrapper. Though the initial value can have a
1556-
// reabstractable type, the result of the initialization is
1557-
// always the property wrapper type, which is never reabstractable.
1558-
bool needsConvertingInit = false;
1559-
auto *singleVar = varPattern->getSingleVar();
1560-
if (!(singleVar && singleVar->getOriginalWrappedProperty())) {
1561-
loweredResultTy = getLoweredType(origType, substType);
1562-
loweredSubstTy = getLoweredType(substType);
1563-
needsConvertingInit = loweredResultTy != loweredSubstTy;
1564-
}
1565-
1566-
if (needsConvertingInit) {
1567-
Conversion conversion = Conversion::getSubstToOrig(
1568-
origType, substType,
1569-
loweredResultTy);
1570-
1571-
ConvertingInitialization convertingInit(conversion,
1572-
SGFContext(memberInit.get()));
1573-
1574-
emitAndStoreInitialValueInto(*this, varPattern, pbd, i, subs,
1575-
origType, substType, &convertingInit);
1576-
1577-
auto finalValue = convertingInit.finishEmission(
1578-
*this, varPattern, ManagedValue::forInContext());
1579-
if (!finalValue.isInContext())
1580-
finalValue.forwardInto(*this, varPattern, memberInit.get());
1581-
} else {
1582-
emitAndStoreInitialValueInto(*this, varPattern, pbd, i, subs,
1583-
origType, substType, memberInit.get());
1584-
}
1585-
}
1593+
emitMemberInitializer(dc, selfDecl, pbd, subs);
15861594
}
15871595
}
15881596
}

lib/SILGen/SILGenFunction.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
802802
void emitMemberInitializers(DeclContext *dc, VarDecl *selfDecl,
803803
NominalTypeDecl *nominal);
804804

805+
/// Generates code to initialize stored property from its
806+
/// initializer.
807+
///
808+
/// \param dc The DeclContext containing the current function.
809+
/// \param selfDecl The 'self' declaration within the current function.
810+
/// \param field The stored property that has to be initialized.
811+
/// \param substitutions The substitutions to apply to initializer and setter.
812+
void emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
813+
PatternBindingDecl *field,
814+
SubstitutionMap substitutions);
815+
805816
void emitMemberInitializationViaInitAccessor(DeclContext *dc,
806817
VarDecl *selfDecl,
807818
PatternBindingDecl *member,

0 commit comments

Comments
 (0)