Skip to content

Commit 47f046e

Browse files
authored
Merge pull request #18768 from jckarter/keypath-let
Preserve 'let'-ness of stored properties in key paths.
2 parents 537954f + 70c60e5 commit 47f046e

File tree

14 files changed

+230
-110
lines changed

14 files changed

+230
-110
lines changed

include/swift/ABI/KeyPath.h

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,65 +82,78 @@ class KeyPathComponentHeader {
8282
offset;
8383
}
8484

85+
static constexpr uint32_t isLetBit(bool isLet) {
86+
return isLet ? 0 : _SwiftKeyPathComponentHeader_StoredMutableFlag;
87+
}
88+
8589
public:
8690
static constexpr bool offsetCanBeInline(unsigned offset) {
8791
return offset <= _SwiftKeyPathComponentHeader_MaximumOffsetPayload;
8892
}
8993

9094
constexpr static KeyPathComponentHeader
91-
forStructComponentWithInlineOffset(unsigned offset) {
95+
forStructComponentWithInlineOffset(bool isLet,
96+
unsigned offset) {
9297
return KeyPathComponentHeader(
9398
(_SwiftKeyPathComponentHeader_StructTag
94-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
95-
| validateInlineOffset(offset));
99+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
100+
| validateInlineOffset(offset)
101+
| isLetBit(isLet));
96102
}
97103

98104
constexpr static KeyPathComponentHeader
99-
forStructComponentWithOutOfLineOffset() {
105+
forStructComponentWithOutOfLineOffset(bool isLet) {
100106
return KeyPathComponentHeader(
101107
(_SwiftKeyPathComponentHeader_StructTag
102-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
103-
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload);
108+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
109+
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload
110+
| isLetBit(isLet));
104111
}
105112

106113
constexpr static KeyPathComponentHeader
107-
forStructComponentWithUnresolvedFieldOffset() {
114+
forStructComponentWithUnresolvedFieldOffset(bool isLet) {
108115
return KeyPathComponentHeader(
109116
(_SwiftKeyPathComponentHeader_StructTag
110-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
111-
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload);
117+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
118+
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload
119+
| isLetBit(isLet));
112120
}
113121

114122
constexpr static KeyPathComponentHeader
115-
forClassComponentWithInlineOffset(unsigned offset) {
123+
forClassComponentWithInlineOffset(bool isLet,
124+
unsigned offset) {
116125
return KeyPathComponentHeader(
117126
(_SwiftKeyPathComponentHeader_ClassTag
118-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
119-
| validateInlineOffset(offset));
127+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
128+
| validateInlineOffset(offset)
129+
| isLetBit(isLet));
120130
}
121131

122132
constexpr static KeyPathComponentHeader
123-
forClassComponentWithOutOfLineOffset() {
133+
forClassComponentWithOutOfLineOffset(bool isLet) {
124134
return KeyPathComponentHeader(
125135
(_SwiftKeyPathComponentHeader_ClassTag
126-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
127-
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload);
136+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
137+
| _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload
138+
| isLetBit(isLet));
128139
}
129140

130141
constexpr static KeyPathComponentHeader
131-
forClassComponentWithUnresolvedFieldOffset() {
142+
forClassComponentWithUnresolvedFieldOffset(bool isLet) {
132143
return KeyPathComponentHeader(
133144
(_SwiftKeyPathComponentHeader_ClassTag
134-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
135-
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload);
145+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
146+
| _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload
147+
| isLetBit(isLet));
136148
}
137149

138150
constexpr static KeyPathComponentHeader
139-
forClassComponentWithUnresolvedIndirectOffset() {
151+
forClassComponentWithUnresolvedIndirectOffset(bool isLet) {
140152
return KeyPathComponentHeader(
141153
(_SwiftKeyPathComponentHeader_ClassTag
142-
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
143-
| _SwiftKeyPathComponentHeader_UnresolvedIndirectOffsetPayload);
154+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift)
155+
| _SwiftKeyPathComponentHeader_UnresolvedIndirectOffsetPayload
156+
| isLetBit(isLet));
144157
}
145158

146159
constexpr static KeyPathComponentHeader

include/swift/Runtime/Metadata.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,10 @@ void verifyMangledNameRoundtrip(const Metadata *metadata);
766766
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
767767
const TypeContextDescriptor *swift_getTypeContextDescriptor(const Metadata *type);
768768

769+
// Defined in KeyPath.swift in the standard library.
770+
SWIFT_RUNTIME_EXPORT
771+
const HeapObject *swift_getKeyPath(const void *pattern, const void *arguments);
772+
769773
} // end namespace swift
770774

771775
#endif // SWIFT_RUNTIME_METADATA_H

lib/IRGen/GenKeyPath.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -773,22 +773,23 @@ emitKeyPathComponent(IRGenModule &IGM,
773773
case KeyPathPatternComponent::Kind::StoredProperty: {
774774
auto property = cast<VarDecl>(component.getStoredPropertyDecl());
775775

776-
auto addFixedOffset = [&](bool isStruct, llvm::Constant *offset) {
776+
auto addFixedOffset = [&](bool isStruct, bool isLet,
777+
llvm::Constant *offset) {
777778
if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
778779
auto offsetValue = offsetInt->getValue().getZExtValue();
779780
if (KeyPathComponentHeader::offsetCanBeInline(offsetValue)) {
780781
auto header = isStruct
781782
? KeyPathComponentHeader
782-
::forStructComponentWithInlineOffset(offsetValue)
783+
::forStructComponentWithInlineOffset(isLet, offsetValue)
783784
: KeyPathComponentHeader
784-
::forClassComponentWithInlineOffset(offsetValue);
785+
::forClassComponentWithInlineOffset(isLet, offsetValue);
785786
fields.addInt32(header.getData());
786787
return;
787788
}
788789
}
789790
auto header = isStruct
790-
? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset()
791-
: KeyPathComponentHeader::forClassComponentWithOutOfLineOffset();
791+
? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset(isLet)
792+
: KeyPathComponentHeader::forClassComponentWithOutOfLineOffset(isLet);
792793
fields.addInt32(header.getData());
793794
fields.add(llvm::ConstantExpr::getTruncOrBitCast(offset, IGM.Int32Ty));
794795
};
@@ -801,7 +802,7 @@ emitKeyPathComponent(IRGenModule &IGM,
801802
loweredBaseTy,
802803
property)) {
803804
// We have a known constant fixed offset.
804-
addFixedOffset(/*struct*/ true, offset);
805+
addFixedOffset(/*struct*/ true, property->isLet(), offset);
805806
break;
806807
}
807808

@@ -811,7 +812,7 @@ emitKeyPathComponent(IRGenModule &IGM,
811812
auto fieldOffset = metadataLayout.getStaticFieldOffset(property);
812813

813814
auto header = KeyPathComponentHeader
814-
::forStructComponentWithUnresolvedFieldOffset();
815+
::forStructComponentWithUnresolvedFieldOffset(property->isLet());
815816
fields.addInt32(header.getData());
816817
fields.addInt32(fieldOffset.getValue());
817818
break;
@@ -829,14 +830,14 @@ emitKeyPathComponent(IRGenModule &IGM,
829830
loweredBaseTy,
830831
property);
831832
assert(offset && "no constant offset for ConstantDirect field?!");
832-
addFixedOffset(/*struct*/ false, offset);
833+
addFixedOffset(/*struct*/ false, property->isLet(), offset);
833834
break;
834835
}
835836
case FieldAccess::NonConstantDirect: {
836837
// A constant offset that's determined at class realization time.
837838
// We have to load the offset from a global ivar.
838839
auto header = KeyPathComponentHeader
839-
::forClassComponentWithUnresolvedIndirectOffset();
840+
::forClassComponentWithUnresolvedIndirectOffset(property->isLet());
840841
fields.addInt32(header.getData());
841842
fields.addAlignmentPadding(IGM.getPointerAlignment());
842843
auto offsetVar = IGM.getAddrOfFieldOffset(property, NotForDefinition);
@@ -846,8 +847,8 @@ emitKeyPathComponent(IRGenModule &IGM,
846847
case FieldAccess::ConstantIndirect: {
847848
// An offset that depends on the instance's generic parameterization,
848849
// but whose field offset is at a known vtable offset.
849-
auto header =
850-
KeyPathComponentHeader::forClassComponentWithUnresolvedFieldOffset();
850+
auto header = KeyPathComponentHeader
851+
::forClassComponentWithUnresolvedFieldOffset(property->isLet());
851852
fields.addInt32(header.getData());
852853
auto fieldOffset =
853854
getClassFieldOffsetOffset(IGM,

stdlib/public/SwiftShims/KeyPath.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,23 @@ static const __swift_uint32_t _SwiftKeyPathComponentHeader_ExternalTag
5959
static const __swift_uint32_t
6060
_SwiftKeyPathComponentHeader_TrivialPropertyDescriptorMarker = 0U;
6161

62+
static const __swift_uint32_t _SwiftKeyPathComponentHeader_StoredOffsetPayloadMask
63+
= 0x007FFFFFU;
64+
6265
static const __swift_uint32_t _SwiftKeyPathComponentHeader_MaximumOffsetPayload
63-
= 0x00FFFFFCU;
66+
= 0x007FFFFCU;
6467

6568
static const __swift_uint32_t _SwiftKeyPathComponentHeader_UnresolvedIndirectOffsetPayload
66-
= 0x00FFFFFDU;
69+
= 0x007FFFFDU;
6770

6871
static const __swift_uint32_t _SwiftKeyPathComponentHeader_UnresolvedFieldOffsetPayload
69-
= 0x00FFFFFEU;
72+
= 0x007FFFFEU;
7073

7174
static const __swift_uint32_t _SwiftKeyPathComponentHeader_OutOfLineOffsetPayload
72-
= 0x00FFFFFFU;
75+
= 0x007FFFFFU;
76+
77+
static const __swift_uint32_t _SwiftKeyPathComponentHeader_StoredMutableFlag
78+
= 0x00800000U;
7379

7480
static const __swift_uint32_t _SwiftKeyPathComponentHeader_OptionalChainPayload
7581
= 0;

0 commit comments

Comments
 (0)