Skip to content

Commit e49e4f9

Browse files
committed
[SILGen] NFC: Factor out logic from GetterSetterComponent to its base
Factor our following logic: - Applying setter to its base value - `newValue` emission This would be useful for init accessor emission as well.
1 parent 4c466f2 commit e49e4f9

File tree

1 file changed

+125
-120
lines changed

1 file changed

+125
-120
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 125 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,114 @@ namespace {
14371437
AccessorDecl *getAccessorDecl() const {
14381438
return cast<AccessorDecl>(Accessor.getFuncDecl());
14391439
}
1440+
1441+
ManagedValue emitValue(SILGenFunction &SGF, SILLocation loc, VarDecl *field,
1442+
Type fieldType, ArgumentSource &&value,
1443+
CanSILFunctionType accessorTy) {
1444+
SILFunctionConventions accessorConv(accessorTy, SGF.SGM.M);
1445+
1446+
// FIXME: This should use CallEmission instead of doing everything
1447+
// manually.
1448+
assert(value.isRValue());
1449+
ManagedValue Mval =
1450+
std::move(value).asKnownRValue(SGF).getAsSingleValue(SGF, loc);
1451+
auto param = accessorTy->getParameters()[0];
1452+
SILType loweredSubstArgType = Mval.getType();
1453+
if (param.isIndirectInOut()) {
1454+
loweredSubstArgType =
1455+
SILType::getPrimitiveAddressType(loweredSubstArgType.getASTType());
1456+
}
1457+
auto loweredSubstParamTy = SILType::getPrimitiveType(
1458+
param.getArgumentType(SGF.SGM.M, accessorTy,
1459+
SGF.getTypeExpansionContext()),
1460+
loweredSubstArgType.getCategory());
1461+
// Handle reabstraction differences.
1462+
if (Mval.getType() != loweredSubstParamTy) {
1463+
Mval = SGF.emitSubstToOrigValue(
1464+
loc, Mval, SGF.SGM.Types.getAbstractionPattern(field),
1465+
fieldType->getCanonicalType());
1466+
}
1467+
1468+
// If we need the argument in memory, materialize an address.
1469+
if (accessorConv.getSILArgumentConvention(0).isIndirectConvention() &&
1470+
!Mval.getType().isAddress()) {
1471+
Mval = Mval.materialize(SGF, loc);
1472+
}
1473+
1474+
return Mval;
1475+
}
1476+
1477+
std::pair<SILValue, CanSILFunctionType>
1478+
applySetterToBase(SILGenFunction &SGF, SILLocation loc, SILDeclRef setter,
1479+
ManagedValue base) const {
1480+
auto setterFRef = [&]() -> SILValue {
1481+
auto setterInfo =
1482+
SGF.getConstantInfo(SGF.getTypeExpansionContext(), setter);
1483+
if (setter.hasDecl() && setter.getDecl()->shouldUseObjCDispatch()) {
1484+
// Emit a thunk we might have to bridge arguments.
1485+
auto foreignSetterThunk = setter.asForeign(false);
1486+
return SGF
1487+
.emitDynamicMethodRef(
1488+
loc, foreignSetterThunk,
1489+
SGF.SGM.Types
1490+
.getConstantInfo(SGF.getTypeExpansionContext(),
1491+
foreignSetterThunk)
1492+
.SILFnType)
1493+
.getValue();
1494+
}
1495+
1496+
return SGF.emitGlobalFunctionRef(loc, setter, setterInfo);
1497+
}();
1498+
1499+
auto getSetterType = [&](SILValue setterFRef) {
1500+
CanSILFunctionType setterTy =
1501+
setterFRef->getType().castTo<SILFunctionType>();
1502+
return setterTy->substGenericArgs(SGF.SGM.M, Substitutions,
1503+
SGF.getTypeExpansionContext());
1504+
};
1505+
1506+
auto setterTy = getSetterType(setterFRef);
1507+
SILFunctionConventions setterConv(setterTy, SGF.SGM.M);
1508+
1509+
// Emit captures for the setter
1510+
SmallVector<SILValue, 4> capturedArgs;
1511+
auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(setter);
1512+
if (!captureInfo.getCaptures().empty()) {
1513+
SmallVector<ManagedValue, 4> captures;
1514+
SGF.emitCaptures(loc, setter, CaptureEmission::AssignByWrapper,
1515+
captures);
1516+
1517+
for (auto capture : captures)
1518+
capturedArgs.push_back(capture.forward(SGF));
1519+
} else {
1520+
assert(base);
1521+
1522+
SILValue capturedBase;
1523+
unsigned argIdx = setterConv.getNumSILArguments() - 1;
1524+
1525+
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
1526+
capturedBase = base.getValue();
1527+
} else if (base.getType().isAddress() &&
1528+
base.getType().getObjectType() ==
1529+
setterConv.getSILArgumentType(
1530+
argIdx, SGF.getTypeExpansionContext())) {
1531+
// If the base is a reference and the setter expects a value, emit a
1532+
// load. This pattern is emitted for property wrappers with a
1533+
// nonmutating setter, for example.
1534+
capturedBase = SGF.B.createTrivialLoadOr(
1535+
loc, base.getValue(), LoadOwnershipQualifier::Copy);
1536+
} else {
1537+
capturedBase = base.copy(SGF, loc).forward(SGF);
1538+
}
1539+
1540+
capturedArgs.push_back(capturedBase);
1541+
}
1542+
1543+
PartialApplyInst *setterPAI =
1544+
SGF.B.createPartialApply(loc, setterFRef, Substitutions, capturedArgs,
1545+
ParameterConvention::Direct_Guaranteed);
1546+
return {SGF.emitManagedRValueWithCleanup(setterPAI).getValue(), setterTy};
1547+
}
14401548
};
14411549

14421550
class GetterSetterComponent
@@ -1592,32 +1700,6 @@ namespace {
15921700
assert(!ActorIso && "no support for cross-actor set operations");
15931701
SILDeclRef setter = Accessor;
15941702

1595-
auto getSetterFRef = [&]() -> SILValue {
1596-
auto setterInfo =
1597-
SGF.getConstantInfo(SGF.getTypeExpansionContext(), setter);
1598-
if (setter.hasDecl() && setter.getDecl()->shouldUseObjCDispatch()) {
1599-
// Emit a thunk we might have to bridge arguments.
1600-
auto foreignSetterThunk = setter.asForeign(false);
1601-
return SGF
1602-
.emitDynamicMethodRef(
1603-
loc, foreignSetterThunk,
1604-
SGF.SGM.Types
1605-
.getConstantInfo(SGF.getTypeExpansionContext(),
1606-
foreignSetterThunk)
1607-
.SILFnType)
1608-
.getValue();
1609-
}
1610-
1611-
return SGF.emitGlobalFunctionRef(loc, setter, setterInfo);
1612-
};
1613-
1614-
auto getSetterType = [&](SILValue setterFRef) {
1615-
CanSILFunctionType setterTy =
1616-
setterFRef->getType().castTo<SILFunctionType>();
1617-
return setterTy->substGenericArgs(SGF.SGM.M, Substitutions,
1618-
SGF.getTypeExpansionContext());
1619-
};
1620-
16211703
auto emitPartialInitAccessorApply =
16221704
[&](AccessorDecl *initAccessor) -> SILValue {
16231705
assert(initAccessor->isInitAccessor());
@@ -1637,83 +1719,6 @@ namespace {
16371719
return SGF.emitManagedRValueWithCleanup(initPAI).getValue();
16381720
};
16391721

1640-
auto emitPartialSetterApply =
1641-
[&](SILValue setterFRef,
1642-
const SILFunctionConventions &setterConv) -> ManagedValue {
1643-
// Emit captures for thI e setter
1644-
SmallVector<SILValue, 4> capturedArgs;
1645-
auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(setter);
1646-
if (!captureInfo.getCaptures().empty()) {
1647-
SmallVector<ManagedValue, 4> captures;
1648-
SGF.emitCaptures(loc, setter, CaptureEmission::AssignByWrapper,
1649-
captures);
1650-
1651-
for (auto capture : captures)
1652-
capturedArgs.push_back(capture.forward(SGF));
1653-
} else {
1654-
assert(base);
1655-
1656-
SILValue capturedBase;
1657-
unsigned argIdx = setterConv.getNumSILArguments() - 1;
1658-
1659-
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
1660-
capturedBase = base.getValue();
1661-
} else if (base.getType().isAddress() &&
1662-
base.getType().getObjectType() ==
1663-
setterConv.getSILArgumentType(
1664-
argIdx, SGF.getTypeExpansionContext())) {
1665-
// If the base is a reference and the setter expects a value, emit a
1666-
// load. This pattern is emitted for property wrappers with a
1667-
// nonmutating setter, for example.
1668-
capturedBase = SGF.B.createTrivialLoadOr(
1669-
loc, base.getValue(), LoadOwnershipQualifier::Copy);
1670-
} else {
1671-
capturedBase = base.copy(SGF, loc).forward(SGF);
1672-
}
1673-
1674-
capturedArgs.push_back(capturedBase);
1675-
}
1676-
1677-
PartialApplyInst *setterPAI = SGF.B.createPartialApply(
1678-
loc, setterFRef, Substitutions, capturedArgs,
1679-
ParameterConvention::Direct_Guaranteed);
1680-
return SGF.emitManagedRValueWithCleanup(setterPAI);
1681-
};
1682-
1683-
auto emitValue =
1684-
[&](VarDecl *field, Type fieldType, CanSILFunctionType setterTy,
1685-
const SILFunctionConventions &setterConv) -> ManagedValue {
1686-
// FIXME: This should use CallEmission instead of doing everything
1687-
// manually.
1688-
assert(value.isRValue());
1689-
ManagedValue Mval =
1690-
std::move(value).asKnownRValue(SGF).getAsSingleValue(SGF, loc);
1691-
auto param = setterTy->getParameters()[0];
1692-
SILType loweredSubstArgType = Mval.getType();
1693-
if (param.isIndirectInOut()) {
1694-
loweredSubstArgType = SILType::getPrimitiveAddressType(
1695-
loweredSubstArgType.getASTType());
1696-
}
1697-
auto loweredSubstParamTy = SILType::getPrimitiveType(
1698-
param.getArgumentType(SGF.SGM.M, setterTy,
1699-
SGF.getTypeExpansionContext()),
1700-
loweredSubstArgType.getCategory());
1701-
// Handle reabstraction differences.
1702-
if (Mval.getType() != loweredSubstParamTy) {
1703-
Mval = SGF.emitSubstToOrigValue(
1704-
loc, Mval, SGF.SGM.Types.getAbstractionPattern(field),
1705-
fieldType->getCanonicalType());
1706-
}
1707-
1708-
// If we need the argument in memory, materialize an address.
1709-
if (setterConv.getSILArgumentConvention(0).isIndirectConvention() &&
1710-
!Mval.getType().isAddress()) {
1711-
Mval = Mval.materialize(SGF, loc);
1712-
}
1713-
1714-
return Mval;
1715-
};
1716-
17171722
if (canRewriteSetAsInitAccessor(SGF)) {
17181723
// Emit an assign_or_init with the allocating initializer function and the
17191724
// setter function as arguments. DefiniteInitialization will then decide
@@ -1730,16 +1735,16 @@ namespace {
17301735
field->getOpaqueAccessor(AccessorKind::Init));
17311736

17321737
// Emit the set accessor function partially applied to the base.
1733-
auto setterFRef = getSetterFRef();
1734-
auto setterTy = getSetterType(setterFRef);
1735-
SILFunctionConventions setterConv(setterTy, SGF.SGM.M);
1736-
auto setterFn = emitPartialSetterApply(setterFRef, setterConv);
1738+
SILValue setterFn;
1739+
CanSILFunctionType setterTy;
1740+
std::tie(setterFn, setterTy) =
1741+
applySetterToBase(SGF, loc, Accessor, base);
17371742

17381743
// Create the assign_or_init with the initializer and setter.
1739-
auto value = emitValue(field, FieldType, setterTy, setterConv);
1740-
SGF.B.createAssignOrInit(loc, base.getValue(), value.forward(SGF),
1741-
initFn, setterFn.getValue(),
1742-
AssignOrInitInst::Unknown);
1744+
auto Mval =
1745+
emitValue(SGF, loc, field, FieldType, std::move(value), setterTy);
1746+
SGF.B.createAssignOrInit(loc, base.getValue(), Mval.forward(SGF),
1747+
initFn, setterFn, AssignOrInitInst::Unknown);
17431748
return;
17441749
}
17451750

@@ -1802,19 +1807,19 @@ namespace {
18021807
ManagedValue initFn = SGF.emitManagedRValueWithCleanup(initPAI);
18031808

18041809
// Create the allocating setter function. It captures the base address.
1805-
auto setterFRef = getSetterFRef();
1806-
auto setterTy = getSetterType(setterFRef);
1807-
SILFunctionConventions setterConv(setterTy, SGF.SGM.M);
1808-
auto setterFn = emitPartialSetterApply(setterFRef, setterConv);
1810+
SILValue setterFn;
1811+
CanSILFunctionType setterTy;
1812+
std::tie(setterFn, setterTy) =
1813+
applySetterToBase(SGF, loc, Accessor, base);
18091814

18101815
// Create the assign_by_wrapper with the initializer and setter.
18111816

1812-
auto Mval = emitValue(field, FieldType, setterTy, setterConv);
1813-
1814-
SGF.B.createAssignByWrapper(
1815-
loc, Mval.forward(SGF), proj.forward(SGF), initFn.getValue(),
1816-
setterFn.getValue(), AssignByWrapperInst::Unknown);
1817+
auto Mval =
1818+
emitValue(SGF, loc, field, FieldType, std::move(value), setterTy);
18171819

1820+
SGF.B.createAssignByWrapper(loc, Mval.forward(SGF), proj.forward(SGF),
1821+
initFn.getValue(), setterFn,
1822+
AssignByWrapperInst::Unknown);
18181823
return;
18191824
}
18201825

0 commit comments

Comments
 (0)