@@ -39,6 +39,65 @@ enum class FieldAccess : uint8_t {
39
39
ConstantIndirect
40
40
};
41
41
42
+ // / A set of flags describing properties of a class's metadata layout.
43
+ // / The presence or absence of these flags determines how much static
44
+ // / knowledge the compiler has of the layout of this class and its
45
+ // / metadata, which in turn will determine the strategy used to emit
46
+ // / and initialize class metadata.
47
+ enum class ClassMetadataFlags {
48
+ // / Does the class or any of its superclasses have stored properties that
49
+ // / where dropped due to the Swift language version availability of
50
+ // / their types?
51
+ ClassHasMissingMembers = (1 << 0 ),
52
+
53
+ // / Does the class or any of its fragile superclasses have stored
54
+ // / properties of unknown size, which do *not* depend on generic
55
+ // / parameters?
56
+ // /
57
+ // / This is different from the class itself being resilient or
58
+ // / having resilient ancestry, because we still have a fixed layout
59
+ // / for the class metadata in this case.
60
+ // /
61
+ // / In fact, for a class with resilient ancestry, this can still be
62
+ // / false if all of the fields known to us are fixed size.
63
+ ClassHasResilientMembers = (1 << 1 ),
64
+
65
+ // / Is this class or any of its superclasses generic?
66
+ ClassHasGenericAncestry = (1 << 2 ),
67
+
68
+ // / Is this class itself generic via the Swift generic system, ie. not a
69
+ // / lightweight Objective-C generic class?
70
+ ClassIsGeneric = (1 << 3 ),
71
+
72
+ // / Does the class layout depend on the size or alignment of its
73
+ // / generic parameters?
74
+ // /
75
+ // / This can be the case if the class has generic resilient ancestry
76
+ // / that depends on the class's generic parameters, of it it has
77
+ // / fields of generic type that are not fixed size.
78
+ ClassHasGenericLayout = (1 << 4 ),
79
+
80
+ // / Is this class or any of its superclasses resilient from the viewpoint
81
+ // / of the current module? This means that their metadata can change size,
82
+ // / hence field offsets, generic arguments and virtual methods must be
83
+ // / accessed relative to a metadata base global variable.
84
+ // /
85
+ // / Note that a @_fixed_layout class in a resilient module still has
86
+ // / resilient metadata, so any subclasses will have this flag set;
87
+ // / to check for resilient stored property layout, check for
88
+ // / ClassHasResilientMembers.
89
+ ClassHasResilientAncestry = (1 << 5 ),
90
+
91
+ // / Are any of this class's superclasses defined in Objective-C?
92
+ // / This means that field offsets must be loaded from field offset globals
93
+ // / or the field offset vector in the metadata, and the Objective-C runtime
94
+ // / will slide offsets based on the actual superclass size, which is not
95
+ // / known at compile time.
96
+ ClassHasObjCAncestry = (1 << 6 )
97
+ };
98
+
99
+ using ClassMetadataOptions = OptionSet<ClassMetadataFlags>;
100
+
42
101
class ClassLayout {
43
102
// / The statically-known minimum bound on the alignment.
44
103
Alignment MinimumAlign;
@@ -50,18 +109,7 @@ class ClassLayout {
50
109
// / alignment are exact.
51
110
bool IsFixedLayout;
52
111
53
- // / Do instances of this class have a size and layout known at compile time?
54
- // /
55
- // / Note: This is a stronger condition than having a fixed layout. The latter
56
- // / is true even when the class requires sliding ivars by the Objective-C
57
- // / runtime.
58
- bool IsFixedSize;
59
-
60
- // / Does the class metadata require initialization?
61
- bool MetadataRequiresInitialization;
62
-
63
- // / Does the class metadata require relocation?
64
- bool MetadataRequiresRelocation;
112
+ ClassMetadataOptions Options;
65
113
66
114
// / The LLVM type for instances of this class.
67
115
llvm::Type *Ty;
@@ -79,9 +127,7 @@ class ClassLayout {
79
127
80
128
public:
81
129
ClassLayout (const StructLayoutBuilder &builder,
82
- bool isFixedSize,
83
- bool metadataRequiresInitialization,
84
- bool metadataRequiresRelocation,
130
+ ClassMetadataOptions options,
85
131
llvm::Type *classTy,
86
132
ArrayRef<VarDecl *> allStoredProps,
87
133
ArrayRef<FieldAccess> allFieldAccesses,
@@ -96,14 +142,49 @@ class ClassLayout {
96
142
97
143
bool isFixedLayout () const { return IsFixedLayout; }
98
144
99
- bool isFixedSize () const { return IsFixedSize; }
145
+ // / Returns true if the stored property layout of instances of this class
146
+ // / is known at compile time.
147
+ // /
148
+ // / Note that ClassHasResilientAncestry or ClassHasGenericAncestry might
149
+ // / still be true; the former means the class has resilient metadata, so
150
+ // / it might still be @_fixed_layout; the latter means we have a generic
151
+ // / superclass, but it doesn't mean the layout actually depends on any
152
+ // / generic parameters.
153
+ bool isFixedSize () const {
154
+ return !(Options.contains (ClassMetadataFlags::ClassHasMissingMembers) ||
155
+ Options.contains (ClassMetadataFlags::ClassHasResilientMembers) ||
156
+ Options.contains (ClassMetadataFlags::ClassHasGenericLayout) ||
157
+ Options.contains (ClassMetadataFlags::ClassHasObjCAncestry));
158
+ }
100
159
160
+ // / Returns true iff everything about the class metadata layout is statically
161
+ // / known except field offsets and the instance size and alignment.
162
+ // /
163
+ // / Will assert if the class metadata is "more" dynamic; you must check
164
+ // / doesMetadataRequireRelocation() and doesMetadataRequireInitialization()
165
+ // / first.
166
+ bool doesMetadataRequireUpdate () const {
167
+ assert (!doesMetadataRequireInitialization ());
168
+ return (Options.contains (ClassMetadataFlags::ClassHasResilientMembers) ||
169
+ Options.contains (ClassMetadataFlags::ClassHasMissingMembers));
170
+ }
171
+
172
+ // / Returns true iff everything about the class metadata layout is statically
173
+ // / known except the superclass field must be instantiated at runtime because
174
+ // / it is a generic class type.
175
+ // /
176
+ // / Will assert if the class metadata is "more" dynamic; you must check
177
+ // / doesMetadataRequireRelocation() first.
101
178
bool doesMetadataRequireInitialization () const {
102
- return MetadataRequiresInitialization;
179
+ assert (!doesMetadataRequireRelocation ());
180
+ return Options.contains (ClassMetadataFlags::ClassHasGenericAncestry);
103
181
}
104
182
183
+ // / Returns true if the class metadata must be built at runtime because its
184
+ // / size is not known at compile time. This is the most general case.
105
185
bool doesMetadataRequireRelocation () const {
106
- return MetadataRequiresRelocation;
186
+ return (Options.contains (ClassMetadataFlags::ClassHasResilientAncestry) ||
187
+ Options.contains (ClassMetadataFlags::ClassIsGeneric));
107
188
}
108
189
109
190
std::pair<FieldAccess, ElementLayout>
0 commit comments