Skip to content

Commit 0e2526d

Browse files
committed
[move-only] Add move only type lowering variants.
1 parent 92a5dba commit 0e2526d

File tree

2 files changed

+272
-7
lines changed

2 files changed

+272
-7
lines changed

include/swift/SIL/TypeLowering.h

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,19 @@ enum IsInfiniteType_t : bool {
169169
IsInfiniteType = true,
170170
};
171171

172+
/// Does this type contain a move only type that affects type lowering?
173+
enum IsMoveOnly_t : bool {
174+
IsNotMoveOnly = false,
175+
IsMoveOnly = true,
176+
};
177+
172178
/// Extended type information used by SIL.
173179
class TypeLowering {
174180
public:
175181
class RecursiveProperties {
176182
// These are chosen so that bitwise-or merges the flags properly.
183+
//
184+
// clang-format off
177185
enum : unsigned {
178186
NonTrivialFlag = 1 << 0,
179187
NonFixedABIFlag = 1 << 1,
@@ -182,7 +190,9 @@ class TypeLowering {
182190
TypeExpansionSensitiveFlag = 1 << 4,
183191
InfiniteFlag = 1 << 5,
184192
HasRawPointerFlag = 1 << 6,
193+
MoveOnlyFlag = 1 << 7,
185194
};
195+
// clang-format on
186196

187197
uint8_t Flags;
188198
public:
@@ -195,13 +205,15 @@ class TypeLowering {
195205
IsAddressOnly_t isAddressOnly, IsResilient_t isResilient,
196206
IsTypeExpansionSensitive_t isTypeExpansionSensitive =
197207
IsNotTypeExpansionSensitive,
198-
HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer)
208+
HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer,
209+
IsMoveOnly_t isMoveOnly = IsNotMoveOnly)
199210
: Flags((isTrivial ? 0U : NonTrivialFlag) |
200211
(isFixedABI ? 0U : NonFixedABIFlag) |
201212
(isAddressOnly ? AddressOnlyFlag : 0U) |
202213
(isResilient ? ResilientFlag : 0U) |
203214
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0U) |
204-
(hasRawPointer ? HasRawPointerFlag : 0U)) {}
215+
(hasRawPointer ? HasRawPointerFlag : 0U) |
216+
(isMoveOnly ? MoveOnlyFlag : 0U)) {}
205217

206218
constexpr bool operator==(RecursiveProperties p) const {
207219
return Flags == p.Flags;
@@ -228,6 +240,35 @@ class TypeLowering {
228240
return {IsTrivial, IsFixedABI, IsNotAddressOnly, IsResilient};
229241
}
230242

243+
static constexpr RecursiveProperties forMoveOnlyReference() {
244+
return {IsNotTrivial,
245+
IsFixedABI,
246+
IsNotAddressOnly,
247+
IsNotResilient,
248+
IsNotTypeExpansionSensitive,
249+
DoesNotHaveRawPointer,
250+
IsMoveOnly};
251+
}
252+
253+
static constexpr RecursiveProperties forMoveOnlyOpaque() {
254+
return {IsNotTrivial,
255+
IsNotFixedABI,
256+
IsAddressOnly,
257+
IsNotResilient,
258+
IsNotTypeExpansionSensitive,
259+
DoesNotHaveRawPointer,
260+
IsMoveOnly};
261+
}
262+
263+
static constexpr RecursiveProperties forMoveOnlyResilient() {
264+
return {IsTrivial,
265+
IsFixedABI,
266+
IsNotAddressOnly,
267+
IsResilient,
268+
IsNotTypeExpansionSensitive,
269+
DoesNotHaveRawPointer,
270+
IsMoveOnly};
271+
}
231272

232273
void addSubobject(RecursiveProperties other) {
233274
Flags |= other.Flags;
@@ -255,6 +296,9 @@ class TypeLowering {
255296
IsInfiniteType_t isInfinite() const {
256297
return IsInfiniteType_t((Flags & InfiniteFlag) != 0);
257298
}
299+
IsMoveOnly_t isMoveOnly() const {
300+
return IsMoveOnly_t((Flags & MoveOnlyFlag) != 0);
301+
}
258302

259303
void setNonTrivial() { Flags |= NonTrivialFlag; }
260304
void setNonFixedABI() { Flags |= NonFixedABIFlag; }
@@ -265,6 +309,7 @@ class TypeLowering {
265309
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0);
266310
}
267311
void setInfinite() { Flags |= InfiniteFlag; }
312+
void setMoveOnly() { Flags |= MoveOnlyFlag; }
268313
};
269314

270315
private:

lib/SIL/IR/TypeLowering.cpp

Lines changed: 225 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,19 @@ namespace {
171171
// RetTy handleTrivial(CanType);
172172
// RetTy handleTrivial(CanType, RecursiveProperties properties);
173173
// // A reference type.
174+
// RetTy handleReference(CanType);
174175
// RetTy handleReference(CanType, RecursiveProperties properties);
175-
// RetTy handleReference(CanType, RecursiveProperties properties);
176+
// // Non-trivial, move only, loadable
177+
// RetTy handleMoveOnlyReference(CanType, RecursiveProperties properties);
178+
// // Non-trivial, move only, address only
179+
// RetTy handleMoveOnlyAddressOnly(CanType, RecursiveProperties
180+
// properties);
176181
// // Non-trivial and address-only.
177182
// RetTy handleAddressOnly(CanType, RecursiveProperties properties);
178183
// and, if it doesn't override handleTupleType,
179184
// // An aggregate type that's non-trivial.
180-
// RetTy handleNonTrivialAggregate(CanType, RecursiveProperties properties);
185+
// RetTy handleNonTrivialAggregate(CanType, RecursiveProperties
186+
// properties);
181187
//
182188
// Alternatively, it can just implement:
183189
// RetTy handle(CanType, RecursiveProperties properties);
@@ -208,6 +214,16 @@ namespace {
208214
return asImpl().handle(type, properties);
209215
}
210216

217+
RetTy handleMoveOnlyReference(CanType type,
218+
RecursiveProperties properties) {
219+
return asImpl().handle(type, properties);
220+
}
221+
222+
RetTy handleMoveOnlyAddressOnly(CanType type,
223+
RecursiveProperties properties) {
224+
return asImpl().handle(type, properties);
225+
}
226+
211227
RecursiveProperties
212228
mergeIsTypeExpansionSensitive(IsTypeExpansionSensitive_t isSensitive,
213229
RecursiveProperties props) {
@@ -228,12 +244,24 @@ namespace {
228244
RecursiveProperties::forReference());
229245
}
230246

247+
RecursiveProperties getMoveOnlyReferenceRecursiveProperties(
248+
IsTypeExpansionSensitive_t isSensitive) {
249+
return mergeIsTypeExpansionSensitive(isSensitive,
250+
RecursiveProperties::forReference());
251+
}
252+
231253
RecursiveProperties
232254
getOpaqueRecursiveProperties(IsTypeExpansionSensitive_t isSensitive) {
233255
return mergeIsTypeExpansionSensitive(isSensitive,
234256
RecursiveProperties::forOpaque());
235257
}
236258

259+
RecursiveProperties getMoveOnlyOpaqueRecursiveProperties(
260+
IsTypeExpansionSensitive_t isSensitive) {
261+
return mergeIsTypeExpansionSensitive(
262+
isSensitive, RecursiveProperties::forMoveOnlyOpaque());
263+
}
264+
237265
#define IMPL(TYPE, LOWERING) \
238266
RetTy visit##TYPE##Type(Can##TYPE##Type type, AbstractionPattern orig, \
239267
IsTypeExpansionSensitive_t isSensitive) { \
@@ -669,9 +697,19 @@ namespace {
669697
RetTy visitSILMoveOnlyType(CanSILMoveOnlyType type,
670698
AbstractionPattern origType,
671699
IsTypeExpansionSensitive_t isSensitive) {
672-
return asImpl().handleReference(
673-
type->getInnerType()->getCanonicalType(),
674-
getReferenceRecursiveProperties(isSensitive));
700+
AbstractionPattern innerAbstraction = origType.withoutMoveOnly();
701+
CanType innerType = type->getInnerType();
702+
auto &lowering =
703+
TC.getTypeLowering(innerAbstraction, innerType, Expansion);
704+
if (lowering.isAddressOnly()) {
705+
return asImpl().handleMoveOnlyAddressOnly(
706+
type->getCanonicalType(),
707+
getMoveOnlyOpaqueRecursiveProperties(isSensitive));
708+
}
709+
710+
return asImpl().handleMoveOnlyReference(
711+
type->getCanonicalType(),
712+
getMoveOnlyReferenceRecursiveProperties(isSensitive));
675713
}
676714

677715
RetTy handleAggregateByProperties(CanType type, RecursiveProperties props) {
@@ -1477,6 +1515,37 @@ namespace {
14771515
}
14781516
};
14791517

1518+
/// A class for move only types which are non-trivial and loadable
1519+
class MoveOnlyReferenceTypeLowering : public LeafLoadableTypeLowering {
1520+
public:
1521+
MoveOnlyReferenceTypeLowering(SILType type, RecursiveProperties properties,
1522+
TypeExpansionContext forExpansion)
1523+
: LeafLoadableTypeLowering(type, properties, IsReferenceCounted,
1524+
forExpansion) {}
1525+
1526+
SILValue emitCopyValue(SILBuilder &B, SILLocation loc,
1527+
SILValue value) const override {
1528+
if (isa<FunctionRefInst>(value) || isa<DynamicFunctionRefInst>(value) ||
1529+
isa<PreviousDynamicFunctionRefInst>(value))
1530+
return value;
1531+
1532+
if (B.getFunction().hasOwnership())
1533+
return B.createCopyValue(loc, value);
1534+
1535+
B.createStrongRetain(loc, value, B.getDefaultAtomicity());
1536+
return value;
1537+
}
1538+
1539+
void emitDestroyValue(SILBuilder &B, SILLocation loc,
1540+
SILValue value) const override {
1541+
if (B.getFunction().hasOwnership()) {
1542+
B.createDestroyValue(loc, value);
1543+
return;
1544+
}
1545+
B.createStrongRelease(loc, value, B.getDefaultAtomicity());
1546+
}
1547+
};
1548+
14801549
/// A type lowering for loadable @unowned types.
14811550
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
14821551
class Loadable##Name##TypeLowering final : public LeafLoadableTypeLowering { \
@@ -1590,6 +1659,93 @@ namespace {
15901659
}
15911660
};
15921661

1662+
/// A class for non-trivial, address-only, move only types.
1663+
class MoveOnlyAddressOnlyTypeLowering : public TypeLowering {
1664+
public:
1665+
MoveOnlyAddressOnlyTypeLowering(SILType type,
1666+
RecursiveProperties properties,
1667+
TypeExpansionContext forExpansion)
1668+
: TypeLowering(type, properties, IsNotReferenceCounted, forExpansion) {
1669+
assert(properties.isAddressOnly());
1670+
}
1671+
1672+
void emitCopyInto(SILBuilder &B, SILLocation loc, SILValue src,
1673+
SILValue dest, IsTake_t isTake,
1674+
IsInitialization_t isInit) const override {
1675+
assert((B.getModule().getStage() == SILStage::Raw || isTake == true) &&
1676+
"Can only copy move only values in Raw SIL");
1677+
B.createCopyAddr(loc, src, dest, isTake, isInit);
1678+
}
1679+
1680+
SILValue emitLoadOfCopy(SILBuilder &B, SILLocation loc, SILValue addr,
1681+
IsTake_t isTake) const override {
1682+
llvm_unreachable("calling emitLoadOfCopy on non-loadable type");
1683+
}
1684+
1685+
void emitStoreOfCopy(SILBuilder &B, SILLocation loc, SILValue newValue,
1686+
SILValue addr,
1687+
IsInitialization_t isInit) const override {
1688+
llvm_unreachable("calling emitStoreOfCopy on non-loadable type");
1689+
}
1690+
1691+
void emitStore(SILBuilder &B, SILLocation loc, SILValue value,
1692+
SILValue addr, StoreOwnershipQualifier qual) const override {
1693+
llvm_unreachable("calling emitStore on non-loadable type");
1694+
}
1695+
1696+
SILValue emitLoad(SILBuilder &B, SILLocation loc, SILValue addr,
1697+
LoadOwnershipQualifier qual) const override {
1698+
llvm_unreachable("calling emitLoad on non-loadable type");
1699+
}
1700+
1701+
SILValue emitLoweredLoad(SILBuilder &B, SILLocation loc, SILValue addr,
1702+
LoadOwnershipQualifier qual,
1703+
Lowering::TypeLowering::TypeExpansionKind
1704+
expansionKind) const override {
1705+
llvm_unreachable("calling emitLoweredLoad on non-loadable type?!");
1706+
}
1707+
1708+
void emitLoweredStore(SILBuilder &B, SILLocation loc, SILValue value,
1709+
SILValue addr, StoreOwnershipQualifier qual,
1710+
Lowering::TypeLowering::TypeExpansionKind
1711+
expansionKind) const override {
1712+
llvm_unreachable("calling emitLoweredStore on non-loadable type?!");
1713+
}
1714+
1715+
void emitDestroyAddress(SILBuilder &B, SILLocation loc,
1716+
SILValue addr) const override {
1717+
if (!isTrivial())
1718+
B.createDestroyAddr(loc, addr);
1719+
}
1720+
1721+
void emitDestroyRValue(SILBuilder &B, SILLocation loc,
1722+
SILValue value) const override {
1723+
if (!isTrivial())
1724+
B.createDestroyAddr(loc, value);
1725+
}
1726+
1727+
SILValue emitCopyValue(SILBuilder &B, SILLocation loc,
1728+
SILValue value) const override {
1729+
llvm_unreachable("type is not loadable!");
1730+
}
1731+
1732+
SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
1733+
SILValue value,
1734+
TypeExpansionKind style) const override {
1735+
llvm_unreachable("type is not loadable!");
1736+
}
1737+
1738+
void emitDestroyValue(SILBuilder &B, SILLocation loc,
1739+
SILValue value) const override {
1740+
llvm_unreachable("type is not loadable!");
1741+
}
1742+
1743+
void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
1744+
TypeExpansionKind style) const override {
1745+
llvm_unreachable("type is not loadable!");
1746+
}
1747+
};
1748+
15931749
/// A class for Builtin.UnsafeValueBuffer. The only purpose here is
15941750
/// to catch obviously broken attempts to copy or destroy the buffer.
15951751
class UnsafeValueBufferTypeLowering : public AddressOnlyTypeLowering {
@@ -1671,6 +1827,51 @@ namespace {
16711827
}
16721828
};
16731829

1830+
/// Lower address only types as opaque values.
1831+
///
1832+
/// Opaque values behave like loadable leaf types in SIL.
1833+
///
1834+
/// FIXME: When you remove an unreachable, just delete the method.
1835+
class MoveOnlyOpaqueValueTypeLowering : public LeafLoadableTypeLowering {
1836+
public:
1837+
MoveOnlyOpaqueValueTypeLowering(SILType type,
1838+
RecursiveProperties properties,
1839+
TypeExpansionContext forExpansion)
1840+
: LeafLoadableTypeLowering(type, properties, IsNotReferenceCounted,
1841+
forExpansion) {}
1842+
1843+
void emitCopyInto(SILBuilder &B, SILLocation loc, SILValue src,
1844+
SILValue dest, IsTake_t isTake,
1845+
IsInitialization_t isInit) const override {
1846+
llvm_unreachable("copy into");
1847+
}
1848+
1849+
// --- Same as LeafLoadableTypeLowering.
1850+
1851+
SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
1852+
SILValue value,
1853+
TypeExpansionKind style) const override {
1854+
llvm_unreachable("lowered copy");
1855+
}
1856+
1857+
void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
1858+
TypeExpansionKind style) const override {
1859+
llvm_unreachable("destroy value");
1860+
}
1861+
1862+
SILValue emitCopyValue(SILBuilder &B, SILLocation loc,
1863+
SILValue value) const override {
1864+
assert(B.getModule().getStage() == SILStage::Raw &&
1865+
"Can not copy a move only value in non-Raw SIL");
1866+
return B.createCopyValue(loc, value);
1867+
}
1868+
1869+
void emitDestroyValue(SILBuilder &B, SILLocation loc,
1870+
SILValue value) const override {
1871+
B.createDestroyValue(loc, value);
1872+
}
1873+
};
1874+
16741875
/// Build the appropriate TypeLowering subclass for the given type,
16751876
/// which is assumed to already have been lowered.
16761877
class LowerType
@@ -1700,6 +1901,25 @@ namespace {
17001901
return new (TC) ReferenceTypeLowering(silType, properties, Expansion);
17011902
}
17021903

1904+
TypeLowering *handleMoveOnlyReference(CanType type,
1905+
RecursiveProperties properties) {
1906+
auto silType = SILType::getPrimitiveObjectType(type);
1907+
return new (TC)
1908+
MoveOnlyReferenceTypeLowering(silType, properties, Expansion);
1909+
}
1910+
1911+
TypeLowering *handleMoveOnlyAddressOnly(CanType type,
1912+
RecursiveProperties properties) {
1913+
if (!TC.Context.SILOpts.EnableSILOpaqueValues) {
1914+
auto silType = SILType::getPrimitiveAddressType(type);
1915+
return new (TC)
1916+
MoveOnlyAddressOnlyTypeLowering(silType, properties, Expansion);
1917+
}
1918+
auto silType = SILType::getPrimitiveObjectType(type);
1919+
return new (TC)
1920+
MoveOnlyOpaqueValueTypeLowering(silType, properties, Expansion);
1921+
}
1922+
17031923
TypeLowering *handleReference(CanType type) {
17041924
auto silType = SILType::getPrimitiveObjectType(type);
17051925
return new (TC) ReferenceTypeLowering(

0 commit comments

Comments
 (0)