@@ -123,7 +123,7 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
123
123
fields.add (emitMetadataGenerator (rootTy));
124
124
fields.add (emitMetadataGenerator (valueTy));
125
125
126
- // TODO: 32-bit still has a padding word
126
+ // TODO: 32-bit heap object header still has an extra word
127
127
if (SizeTy == Int32Ty) {
128
128
fields.addInt32 (0 );
129
129
}
@@ -155,65 +155,31 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
155
155
// Leave a placeholder for the buffer header, since we need to know the full
156
156
// buffer size to fill it in.
157
157
auto headerPlaceholder = fields.addPlaceholderWithSize (Int32Ty);
158
+ fields.addAlignmentPadding (getPointerAlignment ());
158
159
159
160
auto startOfKeyPathBuffer = fields.getNextOffsetFromGlobal ();
160
161
161
162
// Build out the components.
162
163
auto baseTy = rootTy;
163
164
164
- auto getPropertyOffsetOrIndirectOffset
165
- = [&](SILType loweredBaseTy, VarDecl *property)
166
- -> std::pair<llvm::Constant*, bool > {
167
- llvm::Constant *offset;
168
- bool isResolved;
169
- bool isStruct;
170
- if (loweredBaseTy.getStructOrBoundGenericStruct ()) {
171
- offset = emitPhysicalStructMemberFixedOffset (*this ,
172
- loweredBaseTy,
173
- property);
174
- isStruct = true ;
175
- } else if (loweredBaseTy.getClassOrBoundGenericClass ()) {
176
- offset = tryEmitConstantClassFragilePhysicalMemberOffset (*this ,
177
- loweredBaseTy,
178
- property);
179
- isStruct = false ;
180
- } else {
181
- llvm_unreachable (" property of non-struct, non-class?!" );
182
- }
183
-
184
- // If the offset isn't fixed, try instead to get the field offset vector
185
- // offset for the field to look it up dynamically.
186
- isResolved = offset != nullptr ;
187
- if (!isResolved) {
188
- if (isStruct) {
189
- offset = emitPhysicalStructMemberOffsetOfFieldOffset (
190
- *this , loweredBaseTy, property);
191
- assert (offset && " field is neither fixed-offset nor in offset vector" );
192
- } else {
193
- auto offsetValue = getClassFieldOffset (*this ,
194
- loweredBaseTy.getClassOrBoundGenericClass (),
195
- property);
196
- offset = llvm::ConstantInt::get (Int32Ty, offsetValue.getValue ());
197
- }
198
- }
199
-
200
- return {offset, isResolved};
201
- };
165
+ auto assertPointerAlignment = [&]{
166
+ assert (fields.getNextOffsetFromGlobal () % getPointerAlignment () == Size (0 )
167
+ && " must be pointer-aligned here" );
168
+ };
202
169
203
170
for (unsigned i : indices (pattern->getComponents ())) {
171
+ assertPointerAlignment ();
204
172
SILType loweredBaseTy;
205
173
Lowering::GenericContextScope scope (getSILTypes (),
206
174
pattern->getGenericSignature ());
207
175
loweredBaseTy = getLoweredType (AbstractionPattern::getOpaque (),
208
176
baseTy->getLValueOrInOutObjectType ());
209
-
210
177
auto &component = pattern->getComponents ()[i];
211
178
switch (auto kind = component.getKind ()) {
212
179
case KeyPathPatternComponent::Kind::StoredProperty: {
213
180
auto property = cast<VarDecl>(component.getStoredPropertyDecl ());
214
181
215
182
auto addFixedOffset = [&](bool isStruct, llvm::Constant *offset) {
216
- offset = llvm::ConstantExpr::getTruncOrBitCast (offset, Int32Ty);
217
183
if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
218
184
auto offsetValue = offsetInt->getValue ().getZExtValue ();
219
185
if (KeyPathComponentHeader::offsetCanBeInline (offsetValue)) {
@@ -228,7 +194,7 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
228
194
? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset ()
229
195
: KeyPathComponentHeader::forClassComponentWithOutOfLineOffset ();
230
196
fields.addInt32 (header.getData ());
231
- fields.add (offset);
197
+ fields.add (llvm::ConstantExpr::getTruncOrBitCast ( offset, Int32Ty) );
232
198
};
233
199
234
200
// For a struct stored property, we may know the fixed offset of the field,
@@ -247,11 +213,10 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
247
213
// of the type metadata at instantiation time.
248
214
auto fieldOffset = emitPhysicalStructMemberOffsetOfFieldOffset (
249
215
*this , loweredBaseTy, property);
250
- fieldOffset = llvm::ConstantExpr::getTruncOrBitCast (fieldOffset,
251
- Int32Ty);
252
216
auto header = KeyPathComponentHeader::forStructComponentWithUnresolvedFieldOffset ();
253
217
fields.addInt32 (header.getData ());
254
- fields.add (fieldOffset);
218
+ fields.add (llvm::ConstantExpr::getTruncOrBitCast (fieldOffset,
219
+ Int32Ty));
255
220
break ;
256
221
}
257
222
@@ -276,6 +241,7 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
276
241
auto header =
277
242
KeyPathComponentHeader::forClassComponentWithUnresolvedIndirectOffset ();
278
243
fields.addInt32 (header.getData ());
244
+ fields.addAlignmentPadding (getPointerAlignment ());
279
245
auto offsetVar = getAddrOfFieldOffset (property, /* indirect*/ false ,
280
246
NotForDefinition);
281
247
fields.add (cast<llvm::Constant>(offsetVar.getAddress ()));
@@ -358,17 +324,44 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
358
324
break ;
359
325
}
360
326
case KeyPathPatternComponent::ComputedPropertyId::Property:
361
- idKind = KeyPathComponentHeader::StoredPropertyOffset;
362
- std::tie (idValue, idResolved) =
363
- getPropertyOffsetOrIndirectOffset (loweredBaseTy, id.getProperty ());
364
- idValue = llvm::ConstantExpr::getZExtOrBitCast (idValue, SizeTy);
327
+ // Use the index of the stored property within the aggregate to key
328
+ // the property.
329
+ auto property = id.getProperty ();
330
+ idKind = KeyPathComponentHeader::StoredPropertyIndex;
331
+ if (baseTy->getStructOrBoundGenericStruct ()) {
332
+ idResolved = true ;
333
+ idValue = llvm::ConstantInt::get (SizeTy,
334
+ getPhysicalStructFieldIndex (*this ,
335
+ SILType::getPrimitiveAddressType (baseTy), property));
336
+ } else if (baseTy->getClassOrBoundGenericClass ()) {
337
+ // TODO: This field index would require runtime resolution with Swift
338
+ // native class resilience. We never directly access ObjC-imported
339
+ // ivars so we can disregard ObjC ivar resilience for this computation
340
+ // and start counting at the Swift native root.
341
+ switch (getClassFieldAccess (*this , loweredBaseTy, property)) {
342
+ case FieldAccess::ConstantDirect:
343
+ case FieldAccess::ConstantIndirect:
344
+ case FieldAccess::NonConstantDirect:
345
+ idResolved = true ;
346
+ idValue = llvm::ConstantInt::get (SizeTy,
347
+ getClassFieldIndex (*this ,
348
+ SILType::getPrimitiveAddressType (baseTy), property));
349
+ break ;
350
+ case FieldAccess::NonConstantIndirect:
351
+ llvm_unreachable (" not implemented" );
352
+ }
353
+
354
+ } else {
355
+ llvm_unreachable (" neither struct nor class" );
356
+ }
365
357
break ;
366
358
}
367
359
368
360
auto header = KeyPathComponentHeader::forComputedProperty (componentKind,
369
361
idKind, !isInstantiableInPlace, idResolved);
370
362
371
363
fields.addInt32 (header.getData ());
364
+ fields.addAlignmentPadding (getPointerAlignment ());
372
365
fields.add (idValue);
373
366
374
367
if (isInstantiableInPlace) {
@@ -392,6 +385,7 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
392
385
393
386
// For all but the last component, we pack in the type of the component.
394
387
if (i + 1 != pattern->getComponents ().size ()) {
388
+ fields.addAlignmentPadding (getPointerAlignment ());
395
389
fields.add (emitMetadataGenerator (component.getComponentType ()));
396
390
}
397
391
baseTy = component.getComponentType ();
0 commit comments