Skip to content

Commit 4c2dde5

Browse files
committed
IRGen: Lower external key path components.
The key path pattern needs to include a reference to the external descriptor, along with hooks for lowering its type arguments and indices, if any. The runtime will need to instantiate and interpolate the external component when the key path object is instantiated. While we're here, let's also reserve some more component header bytes for future expansion, since this is an ABI we're going to be living with for a while.
1 parent d365c15 commit 4c2dde5

File tree

21 files changed

+300
-120
lines changed

21 files changed

+300
-120
lines changed

docs/ABI/KeyPaths.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ by previous ABI-stable versions of the Swift compiler.
2525
### Buffer Header
2626

2727
Key path objects begin with the standard Swift heap object header, followed by a
28-
key path object header. Relative to the start of the heap object header:
28+
key path object header. Relative to the end of the heap object header:
2929

3030
Offset | Description
3131
------- | ----------------------------------------------
@@ -40,7 +40,7 @@ following bit fields:
4040
Bits (LSB zero) | Description
4141
--------------- | -----------
4242
0...23 | **Buffer size** in bytes
43-
24...29 | Reserved. Must be zero in Swift 4 runtime
43+
24...29 | Reserved. Must be zero in Swift 4...5 runtime
4444
30 | 1 = Has **reference prefix**, 0 = No reference prefix
4545
31 | 1 = Is **trivial**, 0 = Has destructor
4646

@@ -63,8 +63,8 @@ describing the following component.
6363

6464
Bits (LSB zero) | Description
6565
--------------- | -----------
66-
0...28 | **Payload** (meaning is dependent on component kind)
67-
29...30 | **Component kind**
66+
0...23 | **Payload** (meaning is dependent on component kind)
67+
24...30 | **Component kind**
6868
31 | 1 = **End of reference prefix**, 0 = Not end of reference prefix
6969

7070
If the key path has a *reference prefix*, then exactly one component must have
@@ -73,27 +73,27 @@ that the component after the end of the reference prefix will initiate mutation.
7373

7474
The following *component kinds* are recognized:
7575

76-
Value in bit 30&29 | Description
77-
------------------ | -----------
78-
0 | Struct/tuple/self stored property
79-
1 | Computed
80-
2 | Class stored property
81-
3 | Optional chaining/forcing/wrapping
76+
Value in bits 24...30 | Description
77+
--------------------- | -----------
78+
0 | Struct/tuple/self stored property
79+
1 | Computed
80+
2 | Class stored property
81+
3 | Optional chaining/forcing/wrapping
8282

8383
- A **struct stored property** component, when given
8484
a value of the base type in memory, can project the component value in-place
8585
at a fixed offset within the base value. This applies for struct stored
8686
properties, tuple fields, and the `.self` identity component (which trivially
8787
projects at offset zero). The
8888
*payload* contains the offset in bytes of the projected field in the
89-
aggregate, or the special value `0x1FFF_FFFF`, which indicates that the
89+
aggregate, or the special value `0xFF_FFFF`, which indicates that the
9090
offset is too large to pack into the payload and is stored in the next 32 bits
9191
after the header.
9292
- A **class stored property** component, when given a reference to a class
9393
instance, can project the component value inside the class instance at
9494
a fixed offset. The *payload*
9595
*payload* contains the offset in bytes of the projected field from the
96-
address point of the object, or the special value `0x1FFF_FFFF`, which
96+
address point of the object, or the special value `0xFF_FFFF`, which
9797
indicates that the offset is too large to pack into the payload and is stored
9898
in the next 32 bits after the header.
9999
- An **optional** component performs an operation involving `Optional` values.

include/swift/ABI/KeyPath.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,13 @@ class KeyPathComponentHeader {
204204
: getResolutionStrategy(idKind)));
205205
}
206206

207+
constexpr static KeyPathComponentHeader
208+
forExternalComponent() {
209+
return KeyPathComponentHeader(
210+
_SwiftKeyPathComponentHeader_ExternalTag
211+
<< _SwiftKeyPathComponentHeader_DiscriminatorShift);
212+
}
213+
207214
constexpr uint32_t getData() const { return Data; }
208215
};
209216

include/swift/AST/GenericEnvironment.h

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,25 @@
2929

3030
namespace swift {
3131

32+
class ArchetypeType;
3233
class GenericSignatureBuilder;
3334
class ASTContext;
3435
class GenericTypeParamType;
3536
class SILModule;
3637
class SILType;
3738

39+
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
40+
/// the mapping of interface types to archetypes.
41+
class QueryInterfaceTypeSubstitutions {
42+
const GenericEnvironment *self;
43+
44+
public:
45+
QueryInterfaceTypeSubstitutions(const GenericEnvironment *self)
46+
: self(self) { }
47+
48+
Type operator()(SubstitutableType *type) const;
49+
};
50+
3851
/// Describes the mapping between archetypes and interface types for the
3952
/// generic parameters of a DeclContext.
4053
///
@@ -66,23 +79,12 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
6679
GenericEnvironment(GenericSignature *signature,
6780
GenericSignatureBuilder *builder);
6881

69-
friend class ArchetypeType;
70-
friend class GenericSignatureBuilder;
82+
friend ArchetypeType;
83+
friend GenericSignatureBuilder;
7184

7285
GenericSignatureBuilder *getGenericSignatureBuilder() const { return Builder; }
7386

74-
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
75-
/// the mapping of interface types to archetypes.
76-
class QueryInterfaceTypeSubstitutions {
77-
const GenericEnvironment *self;
78-
79-
public:
80-
QueryInterfaceTypeSubstitutions(const GenericEnvironment *self)
81-
: self(self) { }
82-
83-
Type operator()(SubstitutableType *type) const;
84-
};
85-
friend class QueryInterfaceTypeSubstitutions;
87+
friend QueryInterfaceTypeSubstitutions;
8688

8789
public:
8890
GenericSignature *getGenericSignature() const {

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ NODE(PartialApplyObjCForwarder)
132132
NODE(PostfixOperator)
133133
NODE(PrefixOperator)
134134
NODE(PrivateDeclName)
135+
NODE(PropertyDescriptor)
135136
CONTEXT_NODE(Protocol)
136137
NODE(ProtocolConformance)
137138
NODE(ProtocolDescriptor)

include/swift/IRGen/Linking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ class LinkEntity {
140140
/// The pointer is a ClassDecl*.
141141
ClassMetadataBaseOffset,
142142

143+
/// The property descriptor for a public property or subscript.
144+
/// The pointer is an AbstractStorageDecl*.
145+
PropertyDescriptor,
146+
143147
/// The nominal type descriptor for a nominal type.
144148
/// The pointer is a NominalTypeDecl*.
145149
NominalTypeDescriptor,
@@ -481,6 +485,12 @@ class LinkEntity {
481485
return entity;
482486
}
483487

488+
static LinkEntity forPropertyDescriptor(AbstractStorageDecl *decl) {
489+
LinkEntity entity;
490+
entity.setForDecl(Kind::PropertyDescriptor, decl);
491+
return entity;
492+
}
493+
484494
static LinkEntity forModuleDescriptor(ModuleDecl *decl) {
485495
LinkEntity entity;
486496
entity.setForDecl(Kind::ModuleDescriptor, decl);

lib/AST/GenericEnvironment.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,7 @@ Type TypeBase::mapTypeOutOfContext() {
132132
SubstFlags::AllowLoweredTypes);
133133
}
134134

135-
Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
136-
SubstitutableType *type) const {
135+
Type QueryInterfaceTypeSubstitutions::operator()(SubstitutableType *type) const{
137136
if (auto gp = type->getAs<GenericTypeParamType>()) {
138137
// Find the index into the parallel arrays of generic parameters and
139138
// context types.
@@ -148,7 +147,7 @@ Type GenericEnvironment::QueryInterfaceTypeSubstitutions::operator()(
148147
// If the context type isn't already known, lazily create it.
149148
Type contextType = self->getContextTypes()[index];
150149
if (!contextType) {
151-
assert(self->Builder && "Missing generic signature builder for lazy query");
150+
assert(self->Builder &&"Missing generic signature builder for lazy query");
152151
auto equivClass =
153152
self->Builder->resolveEquivalenceClass(
154153
type,

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,9 @@ NodePointer Demangler::demangleMetatype() {
14641464
return createWithChild(Node::Kind::ReflectionMetadataSuperclassDescriptor,
14651465
Ty->getChild(0));
14661466
}
1467+
case 'V':
1468+
return createWithChild(Node::Kind::PropertyDescriptor,
1469+
popNode(isEntity));
14671470
case 'X':
14681471
return demanglePrivateContextDescriptor();
14691472
default:

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ class NodePrinter {
393393
case Node::Kind::PostfixOperator:
394394
case Node::Kind::PrefixOperator:
395395
case Node::Kind::PrivateDeclName:
396+
case Node::Kind::PropertyDescriptor:
396397
case Node::Kind::ProtocolConformance:
397398
case Node::Kind::ProtocolConformanceDescriptor:
398399
case Node::Kind::ProtocolDescriptor:
@@ -1467,6 +1468,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
14671468
Printer << "class metadata base offset for ";
14681469
print(Node->getChild(0));
14691470
return nullptr;
1471+
case Node::Kind::PropertyDescriptor:
1472+
Printer << "property descriptor for ";
1473+
print(Node->getChild(0));
1474+
return nullptr;
14701475
case Node::Kind::NominalTypeDescriptor:
14711476
Printer << "nominal type descriptor for ";
14721477
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,10 @@ void Remangler::mangleNominalTypeDescriptor(Node *node) {
722722
mangleSingleChildNode(node); // type
723723
}
724724

725+
void Remangler::manglePropertyDescriptor(Node *node) {
726+
unreachable("not supported");
727+
}
728+
725729
void Remangler::mangleTypeMetadata(Node *node) {
726730
Out << "M";
727731
mangleSingleChildNode(node); // type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,11 @@ void Remangler::mangleNominalTypeDescriptor(Node *node) {
14031403
Buffer << "Mn";
14041404
}
14051405

1406+
void Remangler::manglePropertyDescriptor(Node *node) {
1407+
mangleSingleChildNode(node);
1408+
Buffer << "MV";
1409+
}
1410+
14061411
void Remangler::mangleNonObjCAttribute(Node *node) {
14071412
Buffer << "TO";
14081413
}

lib/IRGen/GenDecl.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
15061506
case Kind::ObjCMetaclass:
15071507
case Kind::SwiftMetaclassStub:
15081508
case Kind::NominalTypeDescriptor:
1509+
case Kind::PropertyDescriptor:
15091510
case Kind::ClassMetadataBaseOffset:
15101511
case Kind::ProtocolDescriptor:
15111512
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
@@ -1601,6 +1602,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16011602

16021603
case Kind::SwiftMetaclassStub:
16031604
case Kind::ClassMetadataBaseOffset:
1605+
case Kind::PropertyDescriptor:
16041606
case Kind::NominalTypeDescriptor:
16051607
case Kind::ProtocolDescriptor:
16061608
return ::isAvailableExternally(IGM, getDecl());
@@ -3297,8 +3299,7 @@ IRGenModule::getAddrOfClassMetadataBaseOffset(ClassDecl *D,
32973299
SizeTy, DebugTypeInfo());
32983300
}
32993301

3300-
/// Return the address of a nominal type descriptor. Right now, this
3301-
/// must always be for purposes of defining it.
3302+
/// Return the address of a nominal type descriptor.
33023303
llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
33033304
ConstantInit definition) {
33043305
IRGen.addLazyTypeContextDescriptor(D);
@@ -3309,6 +3310,16 @@ llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
33093310
DebugTypeInfo());
33103311
}
33113312

3313+
/// Return the address of a property descriptor.
3314+
llvm::Constant *IRGenModule::getAddrOfPropertyDescriptor(AbstractStorageDecl *D,
3315+
ConstantInit definition) {
3316+
auto entity = LinkEntity::forPropertyDescriptor(D);
3317+
return getAddrOfLLVMVariable(entity, Alignment(4),
3318+
definition,
3319+
TypeContextDescriptorTy,
3320+
DebugTypeInfo());
3321+
}
3322+
33123323
llvm::Constant *IRGenModule::getAddrOfProtocolDescriptor(ProtocolDecl *D,
33133324
ConstantInit definition) {
33143325
if (D->isObjC()) {
@@ -3442,9 +3453,9 @@ void IRGenModule::emitNestedTypeDecls(DeclRange members) {
34423453
case DeclKind::PoundDiagnostic:
34433454
continue;
34443455

3445-
case DeclKind::PatternBinding:
34463456
case DeclKind::Var:
34473457
case DeclKind::Subscript:
3458+
case DeclKind::PatternBinding:
34483459
case DeclKind::Func:
34493460
case DeclKind::Accessor:
34503461
case DeclKind::Constructor:

0 commit comments

Comments
 (0)