Generalize storage implementations to support generalized accessors.

The storage kind has been replaced with three separate "impl kinds",
one for each of the basic access kinds (read, write, and read/write).
This makes it far easier to mix-and-match implementations of different
accessors, as well as subtleties like implementing both a setter
and an independent read/write operation.

AccessStrategy has become a bit more explicit about how exactly the
access should be implemented.  For example, the accessor-based kinds
now carry the exact accessor intended to be used.  Also, I've shifted
responsibilities slightly between AccessStrategy and AccessSemantics
so that AccessSemantics::Ordinary can be used except in the sorts of
semantic-bypasses that accessor synthesis wants.  This requires
knowing the correct DC of the access when computing the access strategy;
the upshot is that SILGenFunction now needs a DC.

Accessor synthesis has been reworked so that only the declarations are
built immediately; body synthesis can be safely delayed out of the main
decl-checking path.  This caused a large number of ramifications,
especially for lazy properties, and greatly inflated the size of this
patch.  That is... really regrettable.  The impetus for changing this
was necessity: I needed to rework accessor synthesis to end its reliance
on distinctions like Stored vs. StoredWithTrivialAccessors, and those
fixes were exposing serious re-entrancy problems, and fixing that... well.
Breaking the fixes apart at this point would be a serious endeavor.
This commit is contained in:
John McCall
2018-06-27 03:28:39 -04:00
parent aef0253c75
commit 9bee3cac5a
66 changed files with 2721 additions and 1869 deletions

View File

@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 424; // Last change: isObjC bits
const uint16_t VERSION_MINOR = 425; // Last change: access impls
using DeclIDField = BCFixed<31>;
@@ -112,13 +112,38 @@ using CharOffsetField = BitOffsetField;
using FileSizeField = BCVBR<16>;
using FileModTimeField = BCVBR<16>;
enum class StorageKind : uint8_t {
Stored, StoredWithTrivialAccessors, StoredWithObservers,
InheritedWithObservers,
Computed, ComputedWithMutableAddress,
Addressed, AddressedWithTrivialAccessors, AddressedWithObservers,
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum class ReadImplKind : uint8_t {
Stored = 0,
Get,
Inherited,
Address
};
using StorageKindField = BCFixed<4>;
using ReadImplKindField = BCFixed<3>;
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum class WriteImplKind : uint8_t {
Immutable = 0,
Stored,
StoredWithObservers,
InheritedWithObservers,
Set,
MutableAddress,
};
using WriteImplKindField = BCFixed<3>;
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
enum class ReadWriteImplKind : uint8_t {
Immutable = 0,
Stored,
MaterializeForSet,
MutableAddress,
MaterializeToTemporary,
};
using ReadWriteImplKindField = BCFixed<3>;
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
@@ -960,7 +985,9 @@ namespace decls_block {
BCFixed<1>, // HasNonPatternBindingInit?
BCFixed<1>, // is getter mutating?
BCFixed<1>, // is setter mutating?
StorageKindField, // StorageKind
ReadImplKindField, // read implementation
WriteImplKindField, // write implementation
ReadWriteImplKindField, // read-write implementation
AccessorCountField, // number of accessors
TypeIDField, // interface type
DeclIDField, // overridden decl
@@ -1097,7 +1124,9 @@ namespace decls_block {
BCFixed<1>, // objc?
BCFixed<1>, // is getter mutating?
BCFixed<1>, // is setter mutating?
StorageKindField, // StorageKind
ReadImplKindField, // read implementation
WriteImplKindField, // write implementation
ReadWriteImplKindField, // read-write implementation
AccessorCountField, // number of accessors
GenericEnvironmentIDField, // generic environment
TypeIDField, // interface type