Skip to content

Commit 3b6f60e

Browse files
authored
Merge pull request #11020 from gottesmm/silgenlvalue_gardening
2 parents 33de799 + 0ddab71 commit 3b6f60e

File tree

1 file changed

+66
-63
lines changed

1 file changed

+66
-63
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 66 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,75 +2001,78 @@ LValue SILGenFunction::emitLValue(Expr *e, AccessKind accessKind) {
20012001

20022002
LValue SILGenLValue::visitRec(Expr *e, AccessKind accessKind,
20032003
AbstractionPattern orig) {
2004-
// Non-lvalue types (references, values, metatypes, etc) form the root of a
2005-
// logical l-value.
2006-
if (!e->getType()->is<LValueType>() && !e->getType()->is<InOutType>()) {
2007-
// Decide if we can evaluate this expression at +0 for the rest of the
2008-
// lvalue.
2009-
SGFContext Ctx;
2010-
ManagedValue rv;
2011-
2012-
// Calls through opaque protocols can be done with +0 rvalues. This allows
2013-
// us to avoid materializing copies of existentials.
2014-
if (SGF.SGM.Types.isIndirectPlusZeroSelfParameter(e->getType()))
2015-
Ctx = SGFContext::AllowGuaranteedPlusZero;
2016-
else if (auto *DRE = dyn_cast<DeclRefExpr>(e)) {
2017-
// Any reference to "self" can be done at +0 so long as it is a direct
2018-
// access, since we know it is guaranteed.
2019-
// TODO: it would be great to factor this even lower into SILGen to the
2020-
// point where we can see that the parameter is +0 guaranteed. Note that
2021-
// this handles the case in initializers where there is actually a stack
2022-
// allocation for it as well.
2023-
if (isa<ParamDecl>(DRE->getDecl()) &&
2024-
DRE->getDecl()->getFullName() == SGF.getASTContext().Id_self &&
2025-
DRE->getDecl()->isImplicit()) {
2026-
Ctx = SGFContext::AllowGuaranteedPlusZero;
2027-
if (SGF.SelfInitDelegationState != SILGenFunction::NormalSelf) {
2028-
// This needs to be inlined since there is a Formal Evaluation Scope
2029-
// in emitRValueForDecl that causing any borrow for this LValue to be
2030-
// popped too soon.
2031-
auto *vd = cast<ParamDecl>(DRE->getDecl());
2032-
ManagedValue selfLValue = SGF.emitLValueForDecl(
2033-
DRE, vd, DRE->getType()->getCanonicalType(), AccessKind::Read,
2034-
DRE->getAccessSemantics());
2035-
rv = SGF.emitRValueForSelfInDelegationInit(
2036-
e, DRE->getType()->getCanonicalType(),
2037-
selfLValue.getLValueAddress(), Ctx)
2038-
.getScalarValue();
2039-
}
2040-
} else if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2041-
// All let values are guaranteed to be held alive across their lifetime,
2042-
// and won't change once initialized. Any loaded value is good for the
2043-
// duration of this expression evaluation.
2044-
if (VD->isLet())
2045-
Ctx = SGFContext::AllowGuaranteedPlusZero;
2046-
}
2004+
// First see if we have an lvalue type. If we do, then quickly handle that and
2005+
// return.
2006+
if (e->getType()->is<LValueType>() || e->getType()->is<InOutType>()) {
2007+
auto lv = visit(e, accessKind);
2008+
// If necessary, handle reabstraction with a SubstToOrigComponent that
2009+
// handles
2010+
// writeback in the original representation.
2011+
if (orig.isValid()) {
2012+
auto &origTL = SGF.getTypeLowering(orig, e->getType()->getRValueType());
2013+
if (lv.getTypeOfRValue() != origTL.getLoweredType().getObjectType())
2014+
lv.addSubstToOrigComponent(orig,
2015+
origTL.getLoweredType().getObjectType());
20472016
}
2017+
return lv;
2018+
}
20482019

2049-
if (!rv) {
2050-
// For an rvalue base, apply the reabstraction (if any) eagerly, since
2051-
// there's no need for writeback.
2052-
if (orig.isValid())
2053-
rv = SGF.emitRValueAsOrig(e, orig,
2054-
SGF.getTypeLowering(orig, e->getType()->getRValueType()));
2055-
else
2056-
rv = SGF.emitRValueAsSingleValue(e, Ctx);
2020+
// Otherwise we have a non-lvalue type (references, values, metatypes,
2021+
// etc). These act as the root of a logical lvalue.
2022+
SGFContext Ctx;
2023+
ManagedValue rv;
2024+
2025+
// Calls through opaque protocols can be done with +0 rvalues. This allows
2026+
// us to avoid materializing copies of existentials.
2027+
if (SGF.SGM.Types.isIndirectPlusZeroSelfParameter(e->getType()))
2028+
Ctx = SGFContext::AllowGuaranteedPlusZero;
2029+
else if (auto *DRE = dyn_cast<DeclRefExpr>(e)) {
2030+
// Any reference to "self" can be done at +0 so long as it is a direct
2031+
// access, since we know it is guaranteed.
2032+
// TODO: it would be great to factor this even lower into SILGen to the
2033+
// point where we can see that the parameter is +0 guaranteed. Note that
2034+
// this handles the case in initializers where there is actually a stack
2035+
// allocation for it as well.
2036+
if (isa<ParamDecl>(DRE->getDecl()) &&
2037+
DRE->getDecl()->getFullName() == SGF.getASTContext().Id_self &&
2038+
DRE->getDecl()->isImplicit()) {
2039+
Ctx = SGFContext::AllowGuaranteedPlusZero;
2040+
if (SGF.SelfInitDelegationState != SILGenFunction::NormalSelf) {
2041+
// This needs to be inlined since there is a Formal Evaluation Scope
2042+
// in emitRValueForDecl that causing any borrow for this LValue to be
2043+
// popped too soon.
2044+
auto *vd = cast<ParamDecl>(DRE->getDecl());
2045+
ManagedValue selfLValue =
2046+
SGF.emitLValueForDecl(DRE, vd, DRE->getType()->getCanonicalType(),
2047+
AccessKind::Read, DRE->getAccessSemantics());
2048+
rv = SGF.emitRValueForSelfInDelegationInit(
2049+
e, DRE->getType()->getCanonicalType(),
2050+
selfLValue.getLValueAddress(), Ctx)
2051+
.getScalarValue();
2052+
}
2053+
} else if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2054+
// All let values are guaranteed to be held alive across their lifetime,
2055+
// and won't change once initialized. Any loaded value is good for the
2056+
// duration of this expression evaluation.
2057+
if (VD->isLet())
2058+
Ctx = SGFContext::AllowGuaranteedPlusZero;
20572059
}
2058-
CanType formalType = getSubstFormalRValueType(e);
2059-
auto typeData = getValueTypeData(formalType, rv.getValue());
2060-
LValue lv;
2061-
lv.add<ValueComponent>(rv, None, typeData, /*isRValue=*/true);
2062-
return lv;
20632060
}
20642061

2065-
auto lv = visit(e, accessKind);
2066-
// If necessary, handle reabstraction with a SubstToOrigComponent that handles
2067-
// writeback in the original representation.
2068-
if (orig.isValid()) {
2069-
auto &origTL = SGF.getTypeLowering(orig, e->getType()->getRValueType());
2070-
if (lv.getTypeOfRValue() != origTL.getLoweredType().getObjectType())
2071-
lv.addSubstToOrigComponent(orig, origTL.getLoweredType().getObjectType());
2062+
if (!rv) {
2063+
// For an rvalue base, apply the reabstraction (if any) eagerly, since
2064+
// there's no need for writeback.
2065+
if (orig.isValid())
2066+
rv = SGF.emitRValueAsOrig(
2067+
e, orig, SGF.getTypeLowering(orig, e->getType()->getRValueType()));
2068+
else
2069+
rv = SGF.emitRValueAsSingleValue(e, Ctx);
20722070
}
2071+
2072+
CanType formalType = getSubstFormalRValueType(e);
2073+
auto typeData = getValueTypeData(formalType, rv.getValue());
2074+
LValue lv;
2075+
lv.add<ValueComponent>(rv, None, typeData, /*isRValue=*/true);
20732076
return lv;
20742077
}
20752078

0 commit comments

Comments
 (0)