Skip to content

Commit 75ac138

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 2abfa25 commit 75ac138

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
@@ -1754,3 +1754,73 @@ ParamDecl *SILGenFunction::isMappedToInitAccessorArgument(VarDecl *property) {
17541754

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

lib/SILGen/SILGenFunction.h

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

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

lib/SILGen/SILGenLValue.cpp

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

14781478
return Mval;
14791479
}
1480-
1481-
std::pair<SILValue, CanSILFunctionType>
1482-
applySetterToBase(SILGenFunction &SGF, SILLocation loc, SILDeclRef setter,
1483-
ManagedValue base) const {
1484-
auto setterFRef = [&]() -> SILValue {
1485-
auto setterInfo =
1486-
SGF.getConstantInfo(SGF.getTypeExpansionContext(), setter);
1487-
if (setter.hasDecl() && setter.getDecl()->shouldUseObjCDispatch()) {
1488-
// Emit a thunk we might have to bridge arguments.
1489-
auto foreignSetterThunk = setter.asForeign(false);
1490-
return SGF
1491-
.emitDynamicMethodRef(
1492-
loc, foreignSetterThunk,
1493-
SGF.SGM.Types
1494-
.getConstantInfo(SGF.getTypeExpansionContext(),
1495-
foreignSetterThunk)
1496-
.SILFnType)
1497-
.getValue();
1498-
}
1499-
1500-
return SGF.emitGlobalFunctionRef(loc, setter, setterInfo);
1501-
}();
1502-
1503-
auto getSetterType = [&](SILValue setterFRef) {
1504-
CanSILFunctionType setterTy =
1505-
setterFRef->getType().castTo<SILFunctionType>();
1506-
return setterTy->substGenericArgs(SGF.SGM.M, Substitutions,
1507-
SGF.getTypeExpansionContext());
1508-
};
1509-
1510-
auto setterTy = getSetterType(setterFRef);
1511-
SILFunctionConventions setterConv(setterTy, SGF.SGM.M);
1512-
1513-
// Emit captures for the setter
1514-
SmallVector<SILValue, 4> capturedArgs;
1515-
auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(setter);
1516-
if (!captureInfo.getCaptures().empty()) {
1517-
SmallVector<ManagedValue, 4> captures;
1518-
SGF.emitCaptures(loc, setter, CaptureEmission::AssignByWrapper,
1519-
captures);
1520-
1521-
for (auto capture : captures)
1522-
capturedArgs.push_back(capture.forward(SGF));
1523-
} else {
1524-
assert(base);
1525-
1526-
SILValue capturedBase;
1527-
unsigned argIdx = setterConv.getNumSILArguments() - 1;
1528-
1529-
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
1530-
capturedBase = base.getValue();
1531-
} else if (base.getType().isAddress() &&
1532-
base.getType().getObjectType() ==
1533-
setterConv.getSILArgumentType(
1534-
argIdx, SGF.getTypeExpansionContext())) {
1535-
// If the base is a reference and the setter expects a value, emit a
1536-
// load. This pattern is emitted for property wrappers with a
1537-
// nonmutating setter, for example.
1538-
capturedBase = SGF.B.createTrivialLoadOr(
1539-
loc, base.getValue(), LoadOwnershipQualifier::Copy);
1540-
} else {
1541-
capturedBase = base.copy(SGF, loc).forward(SGF);
1542-
}
1543-
1544-
capturedArgs.push_back(capturedBase);
1545-
}
1546-
1547-
PartialApplyInst *setterPAI =
1548-
SGF.B.createPartialApply(loc, setterFRef, Substitutions, capturedArgs,
1549-
ParameterConvention::Direct_Guaranteed);
1550-
return {SGF.emitManagedRValueWithCleanup(setterPAI).getValue(), setterTy};
1551-
}
15521480
};
15531481

15541482
class InitAccessorComponent
@@ -1593,8 +1521,8 @@ namespace {
15931521
CanSILFunctionType setterTy;
15941522

15951523
if (auto *setter = field->getOpaqueAccessor(AccessorKind::Set)) {
1596-
std::tie(setterFRef, setterTy) =
1597-
applySetterToBase(SGF, loc, SILDeclRef(setter), base);
1524+
std::tie(setterFRef, setterTy) = SGF.emitApplyOfSetterToBase(
1525+
loc, SILDeclRef(setter), base, Substitutions);
15981526
} else {
15991527
setterFRef = SILUndef::get(initFRef->getType(), SGF.F);
16001528
setterTy = initFRef->getType().castTo<SILFunctionType>();
@@ -1897,7 +1825,7 @@ namespace {
18971825
SILValue setterFn;
18981826
CanSILFunctionType setterTy;
18991827
std::tie(setterFn, setterTy) =
1900-
applySetterToBase(SGF, loc, Accessor, base);
1828+
SGF.emitApplyOfSetterToBase(loc, Accessor, base, Substitutions);
19011829

19021830
// Create the assign_by_wrapper with the initializer and setter.
19031831

0 commit comments

Comments
 (0)