Skip to content

Commit e4e5aa1

Browse files
committed
[SILGen] NFC: Extract application of setter to base into a method on SILGenFunction
This is a preliminary step towards enabling default initialization of init accessor properties in user-defined initializers because this logic would have to be shared by multiple places during SILGen.
1 parent 5e1b9fc commit e4e5aa1

File tree

3 files changed

+78
-75
lines changed

3 files changed

+78
-75
lines changed

lib/SILGen/SILGenFunction.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,3 +1746,73 @@ ParamDecl *SILGenFunction::isMappedToInitAccessorArgument(VarDecl *property) {
17461746

17471747
return arg->second;
17481748
}
1749+
1750+
std::pair<SILValue, CanSILFunctionType>
1751+
SILGenFunction::emitApplyOfSetterToBase(SILLocation loc, SILDeclRef setter,
1752+
ManagedValue base,
1753+
SubstitutionMap substitutions) {
1754+
auto setterFRef = [&]() -> SILValue {
1755+
auto setterInfo = getConstantInfo(getTypeExpansionContext(), setter);
1756+
if (setter.hasDecl() && setter.getDecl()->shouldUseObjCDispatch()) {
1757+
// Emit a thunk we might have to bridge arguments.
1758+
auto foreignSetterThunk = setter.asForeign(false);
1759+
return emitDynamicMethodRef(
1760+
loc, foreignSetterThunk,
1761+
SGM.Types
1762+
.getConstantInfo(getTypeExpansionContext(),
1763+
foreignSetterThunk)
1764+
.SILFnType)
1765+
.getValue();
1766+
}
1767+
1768+
return emitGlobalFunctionRef(loc, setter, setterInfo);
1769+
}();
1770+
1771+
auto getSetterType = [&](SILValue setterFRef) {
1772+
CanSILFunctionType setterTy =
1773+
setterFRef->getType().castTo<SILFunctionType>();
1774+
return setterTy->substGenericArgs(SGM.M, substitutions,
1775+
getTypeExpansionContext());
1776+
};
1777+
1778+
auto setterTy = getSetterType(setterFRef);
1779+
SILFunctionConventions setterConv(setterTy, SGM.M);
1780+
1781+
// Emit captures for the setter
1782+
SmallVector<SILValue, 4> capturedArgs;
1783+
auto captureInfo = SGM.Types.getLoweredLocalCaptures(setter);
1784+
if (!captureInfo.getCaptures().empty()) {
1785+
SmallVector<ManagedValue, 4> captures;
1786+
emitCaptures(loc, setter, CaptureEmission::AssignByWrapper, captures);
1787+
1788+
for (auto capture : captures)
1789+
capturedArgs.push_back(capture.forward(*this));
1790+
} else {
1791+
assert(base);
1792+
1793+
SILValue capturedBase;
1794+
unsigned argIdx = setterConv.getNumSILArguments() - 1;
1795+
1796+
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
1797+
capturedBase = base.getValue();
1798+
} else if (base.getType().isAddress() &&
1799+
base.getType().getObjectType() ==
1800+
setterConv.getSILArgumentType(argIdx,
1801+
getTypeExpansionContext())) {
1802+
// If the base is a reference and the setter expects a value, emit a
1803+
// load. This pattern is emitted for property wrappers with a
1804+
// nonmutating setter, for example.
1805+
capturedBase = B.createTrivialLoadOr(loc, base.getValue(),
1806+
LoadOwnershipQualifier::Copy);
1807+
} else {
1808+
capturedBase = base.copy(*this, loc).forward(*this);
1809+
}
1810+
1811+
capturedArgs.push_back(capturedBase);
1812+
}
1813+
1814+
PartialApplyInst *setterPAI =
1815+
B.createPartialApply(loc, setterFRef, substitutions, capturedArgs,
1816+
ParameterConvention::Direct_Guaranteed);
1817+
return {emitManagedRValueWithCleanup(setterPAI).getValue(), setterTy};
1818+
}

lib/SILGen/SILGenFunction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,11 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
813813
/// value assignment.
814814
void emitInitAccessor(AccessorDecl *accessor);
815815

816+
/// Generates code to emit the given setter reference to the given base value.
817+
std::pair<SILValue, CanSILFunctionType>
818+
emitApplyOfSetterToBase(SILLocation loc, SILDeclRef setter, ManagedValue base,
819+
SubstitutionMap substitutions);
820+
816821
/// Generates code to destroy the instance variables of a class.
817822
///
818823
/// \param selfValue The 'self' value.

lib/SILGen/SILGenLValue.cpp

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1473,78 +1473,6 @@ namespace {
14731473

14741474
return Mval;
14751475
}
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-
}
15481476
};
15491477

15501478
class InitAccessorComponent
@@ -1589,8 +1517,8 @@ namespace {
15891517
CanSILFunctionType setterTy;
15901518

15911519
if (auto *setter = field->getOpaqueAccessor(AccessorKind::Set)) {
1592-
std::tie(setterFRef, setterTy) =
1593-
applySetterToBase(SGF, loc, SILDeclRef(setter), base);
1520+
std::tie(setterFRef, setterTy) = SGF.emitApplyOfSetterToBase(
1521+
loc, SILDeclRef(setter), base, Substitutions);
15941522
} else {
15951523
setterFRef = SILUndef::get(initFRef->getType(), SGF.F);
15961524
setterTy = initFRef->getType().castTo<SILFunctionType>();
@@ -1893,7 +1821,7 @@ namespace {
18931821
SILValue setterFn;
18941822
CanSILFunctionType setterTy;
18951823
std::tie(setterFn, setterTy) =
1896-
applySetterToBase(SGF, loc, Accessor, base);
1824+
SGF.emitApplyOfSetterToBase(loc, Accessor, base, Substitutions);
18971825

18981826
// Create the assign_by_wrapper with the initializer and setter.
18991827

0 commit comments

Comments
 (0)