Skip to content

Commit fc74d52

Browse files
authored
Merge pull request #14809 from jckarter/keypath-resilience
External key path components and key path descriptors
2 parents be19556 + 4c2dde5 commit fc74d52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1521
-721
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/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,8 @@ ERROR(expected_sil_instr_opcode,none,
528528
"expected SIL instruction opcode", ())
529529
ERROR(expected_tok_in_sil_instr,none,
530530
"expected '%0' in SIL instruction", (StringRef))
531+
ERROR(sil_property_generic_signature_mismatch,none,
532+
"sil_property generic signature must match original declaration", ())
531533
ERROR(sil_string_no_encoding,none,
532534
"string_literal instruction requires an encoding", ())
533535
ERROR(sil_string_invalid_encoding,none,

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/AST/GenericSignature.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_AST_GENERIC_SIGNATURE_H
1818
#define SWIFT_AST_GENERIC_SIGNATURE_H
1919

20+
#include "swift/AST/PrintOptions.h"
2021
#include "swift/AST/Requirement.h"
2122
#include "swift/AST/SubstitutionList.h"
2223
#include "swift/AST/Types.h"
@@ -338,7 +339,7 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
338339
TypeArrayView<GenericTypeParamType> genericParams,
339340
ArrayRef<Requirement> requirements);
340341

341-
void print(raw_ostream &OS) const;
342+
void print(raw_ostream &OS, PrintOptions Options = PrintOptions()) const;
342343
void dump() const;
343344
std::string getAsString() const;
344345
};

include/swift/AST/PrintOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/Identifier.h"
1919
#include "swift/AST/TypeOrExtensionDecl.h"
2020
#include "llvm/ADT/Optional.h"
21+
#include "llvm/ADT/DenseMap.h"
2122
#include <limits.h>
2223
#include <vector>
2324

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ namespace swift {
219219
/// This is for bootstrapping. It can't be in SILOptions because the
220220
/// TypeChecker uses it to set resolve the ParameterConvention.
221221
bool EnableSILOpaqueValues = false;
222+
223+
/// Enables key path resilience.
224+
bool EnableKeyPathResilience = false;
222225

223226
/// If set to true, the diagnosis engine can assume the emitted diagnostics
224227
/// will be used in editor. This usually leads to more aggressive fixit.

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);

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,4 +463,7 @@ def enable_verify_exclusivity : Flag<["-"], "enable-verify-exclusivity">,
463463
def disable_verify_exclusivity : Flag<["-"], "disable-verify-exclusivity">,
464464
HelpText<"Diable verification of access markers used to enforce exclusivity.">;
465465

466+
def enable_key_path_resilience : Flag<["-"], "enable-key-path-resilience">,
467+
HelpText<"Enable key path resilience.">;
468+
466469
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

include/swift/Parse/ParseSILSupport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace swift {
3333
virtual bool parseSILWitnessTable(Parser &P) = 0;
3434
virtual bool parseSILDefaultWitnessTable(Parser &P) = 0;
3535
virtual bool parseSILCoverageMap(Parser &P) = 0;
36+
virtual bool parseSILProperty(Parser &P) = 0;
3637
virtual bool parseSILScope(Parser &P) = 0;
3738
};
3839

include/swift/SIL/SILModule.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/SIL/SILFunction.h"
3333
#include "swift/SIL/SILGlobalVariable.h"
3434
#include "swift/SIL/SILPrintContext.h"
35+
#include "swift/SIL/SILProperty.h"
3536
#include "swift/SIL/SILType.h"
3637
#include "swift/SIL/SILVTable.h"
3738
#include "swift/SIL/SILWitnessTable.h"
@@ -103,6 +104,7 @@ class SILModule {
103104
using FunctionListType = llvm::ilist<SILFunction>;
104105
using GlobalListType = llvm::ilist<SILGlobalVariable>;
105106
using VTableListType = llvm::ilist<SILVTable>;
107+
using PropertyListType = llvm::ilist<SILProperty>;
106108
using WitnessTableListType = llvm::ilist<SILWitnessTable>;
107109
using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
108110
using CoverageMapListType = llvm::ilist<SILCoverageMap>;
@@ -119,6 +121,7 @@ class SILModule {
119121
friend SILLayout;
120122
friend SILType;
121123
friend SILVTable;
124+
friend SILProperty;
122125
friend SILUndef;
123126
friend SILWitnessTable;
124127
friend Lowering::SILGenModule;
@@ -184,6 +187,9 @@ class SILModule {
184187

185188
// The list of SILCoverageMaps in the module.
186189
CoverageMapListType coverageMaps;
190+
191+
// The list of SILProperties in the module.
192+
PropertyListType properties;
187193

188194
/// This is the underlying raw stream of OptRecordStream.
189195
///
@@ -458,10 +464,13 @@ class SILModule {
458464
void setOptRecordStream(std::unique_ptr<llvm::yaml::Output> &&Stream,
459465
std::unique_ptr<llvm::raw_ostream> &&RawStream);
460466

467+
PropertyListType &getPropertyList() { return properties; }
468+
const PropertyListType &getPropertyList() const { return properties; }
469+
461470
/// Look for a global variable by name.
462471
///
463472
/// \return null if this module has no such global variable
464-
SILGlobalVariable *lookUpGlobalVariable(StringRef name) const {
473+
SILGlobalVariable *lookUpGlobalVariable(StringRef name) const {
465474
return GlobalVariableMap.lookup(name);
466475
}
467476

include/swift/SIL/SILProperty.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//===--- SILProperty.h - Defines the SILProperty class ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the SILProperty class, which is used to capture the
14+
// metadata about a property definition necessary for it to be resiliently
15+
// included in KeyPaths across modules.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#ifndef SWIFT_SIL_SILPROPERTY_H
20+
#define SWIFT_SIL_SILPROPERTY_H
21+
22+
#include "swift/AST/GenericSignature.h"
23+
#include "swift/SIL/SILAllocated.h"
24+
#include "swift/SIL/SILInstruction.h"
25+
#include "llvm/ADT/ilist_node.h"
26+
#include "llvm/ADT/ilist.h"
27+
28+
namespace swift {
29+
30+
class SILPrintContext;
31+
32+
/// A descriptor for a public property or subscript that can be resiliently
33+
/// referenced from key paths in external modules.
34+
class SILProperty : public llvm::ilist_node<SILProperty>,
35+
public SILAllocated<SILProperty>
36+
{
37+
private:
38+
/// True if serialized.
39+
bool Serialized;
40+
41+
/// The declaration the descriptor represents.
42+
AbstractStorageDecl *Decl;
43+
44+
/// The key path component that represents its implementation.
45+
KeyPathPatternComponent Component;
46+
47+
SILProperty(bool Serialized,
48+
AbstractStorageDecl *Decl,
49+
KeyPathPatternComponent Component)
50+
: Serialized(Serialized), Decl(Decl), Component(Component)
51+
{}
52+
53+
public:
54+
static SILProperty *create(SILModule &M,
55+
bool Serialized,
56+
AbstractStorageDecl *Decl,
57+
KeyPathPatternComponent Component);
58+
59+
bool isSerialized() const { return Serialized; }
60+
61+
AbstractStorageDecl *getDecl() const { return Decl; }
62+
63+
const KeyPathPatternComponent &getComponent() const { return Component; }
64+
65+
void print(SILPrintContext &Ctx) const;
66+
};
67+
68+
} // end namespace swift
69+
70+
namespace llvm {
71+
72+
//===----------------------------------------------------------------------===//
73+
// ilist_traits for SILProperty
74+
//===----------------------------------------------------------------------===//
75+
76+
template <>
77+
struct ilist_traits<::swift::SILProperty>
78+
: public ilist_default_traits<::swift::SILProperty> {
79+
typedef ::swift::SILProperty SILProperty;
80+
81+
public:
82+
static void deleteNode(SILProperty *VT) { VT->~SILProperty(); }
83+
84+
private:
85+
void createNode(const SILProperty &);
86+
};
87+
88+
} // namespace llvm
89+
90+
#endif

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 399; // Last change: @_weakLinked
58+
const uint16_t VERSION_MINOR = 400; // Last change: sil_property
5959

6060
using DeclIDField = BCFixed<31>;
6161

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ class SerializedSILLoader {
132132
/// Deserialize all DefaultWitnessTables in all SILModules.
133133
void getAllDefaultWitnessTables();
134134

135+
/// Deserialize all Properties in all SILModules.
136+
void getAllProperties();
137+
135138
SerializedSILLoader(const SerializedSILLoader &) = delete;
136139
SerializedSILLoader(SerializedSILLoader &&) = delete;
137140
SerializedSILLoader &operator=(const SerializedSILLoader &) = delete;

include/swift/Syntax/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ DECL_KEYWORD(static)
172172
SIL_KEYWORD(undef)
173173
SIL_KEYWORD(sil)
174174
SIL_KEYWORD(sil_stage)
175+
SIL_KEYWORD(sil_property)
175176
SIL_KEYWORD(sil_vtable)
176177
SIL_KEYWORD(sil_global)
177178
SIL_KEYWORD(sil_witness_table)

0 commit comments

Comments
 (0)