@@ -188,32 +188,19 @@ static bool hasMetadataPattern(IRGenModule &IGM, NominalTypeDecl *theDecl) {
188
188
// Protocols must be special-cased in a few places.
189
189
assert (!isa<ProtocolDecl>(theDecl));
190
190
191
- // Classes imported from Objective-C never have a metadata pattern.
192
- if (theDecl->hasClangNode ())
193
- return false ;
194
-
195
- // A generic class, struct, or enum is always initialized at runtime.
191
+ // For classes, we already computed this when we did the layout.
192
+ // FIXME: Try not to call this for classes of other modules, by referencing
193
+ // the metadata accessor instead.
194
+ if (auto *theClass = dyn_cast<ClassDecl>(theDecl))
195
+ return getClassHasMetadataPattern (IGM, theClass);
196
+
197
+ // Ok, we have a value type. If it is generic, it is always initialized
198
+ // at runtime.
196
199
if (theDecl->isGenericContext ())
197
200
return true ;
198
201
199
- // A class with generic ancestry is always initialized at runtime.
200
- // TODO: This should be cached in the ClassDecl since it is checked for in
201
- // several places.
202
- if (auto *theClass = dyn_cast<ClassDecl>(theDecl)) {
203
- Type superclassTy = theClass->getSuperclass ();
204
- while (superclassTy) {
205
- if (superclassTy->getClassOrBoundGenericClass ()->isGenericContext ())
206
- return true ;
207
- superclassTy = superclassTy->getSuperclass (nullptr );
208
- }
209
-
210
- // TODO: check if class fields are resilient. Fixed-size check for value
211
- // types isn't meaningful here.
212
- return false ;
213
- }
214
-
215
- // If we have fields of resilient type, the metadata still has to be
216
- // initialized at runtime.
202
+ // If the type is not fixed-size, its size depends on resilient types,
203
+ // and the metadata is initialized at runtime.
217
204
if (!IGM.getTypeInfoForUnlowered (theDecl->getDeclaredType ()).isFixedSize ())
218
205
return true ;
219
206
@@ -2864,6 +2851,7 @@ namespace {
2864
2851
}
2865
2852
2866
2853
bool HasRuntimeParent = false ;
2854
+
2867
2855
public:
2868
2856
// / The 'metadata flags' field in a class is actually a pointer to
2869
2857
// / the metaclass object for the class.
@@ -3140,7 +3128,15 @@ namespace {
3140
3128
ClassMetadataBuilder (IRGenModule &IGM, ClassDecl *theClass,
3141
3129
const StructLayout &layout,
3142
3130
const ClassLayout &fieldLayout)
3143
- : ClassMetadataBuilderBase(IGM, theClass, layout, fieldLayout) {}
3131
+ : ClassMetadataBuilderBase(IGM, theClass, layout, fieldLayout) {
3132
+
3133
+ assert (layout.isFixedLayout () &&
3134
+ " non-fixed layout classes require a template" );
3135
+ // FIXME: Distinguish Objective-C sliding from resilient layout
3136
+ assert ((fieldLayout.MetadataAccess == FieldAccess::ConstantDirect ||
3137
+ fieldLayout.MetadataAccess == FieldAccess::NonConstantDirect) &&
3138
+ " resilient superclasses require a template" );
3139
+ }
3144
3140
3145
3141
llvm::Constant *getInit () {
3146
3142
return getInitWithSuggestedType (NumHeapMetadataFields,
@@ -3202,11 +3198,6 @@ namespace {
3202
3198
{
3203
3199
typedef GenericMetadataBuilderBase super;
3204
3200
3205
- bool HasDependentFieldOffsetVector = false ;
3206
-
3207
- bool InheritFieldOffsetVectors = false ;
3208
- bool InheritGenericParameters = false ;
3209
-
3210
3201
Size MetaclassPtrOffset = Size::invalid();
3211
3202
Size ClassRODataPtrOffset = Size::invalid();
3212
3203
Size MetaclassRODataPtrOffset = Size::invalid();
@@ -3305,26 +3296,9 @@ namespace {
3305
3296
3306
3297
void noteStartOfFieldOffsets (ClassDecl *whichClass) {
3307
3298
HasDependentMetadata = true ;
3308
-
3309
- if (whichClass == Target) {
3310
- // If the metadata contains a field offset vector for the class itself,
3311
- // then we need to initialize it at runtime.
3312
- HasDependentFieldOffsetVector = true ;
3313
- return ;
3314
- }
3315
-
3316
- // If we have a field offset vector for an ancestor class, we will copy
3317
- // it from our superclass metadata at instantiation time.
3318
- InheritFieldOffsetVectors = true ;
3319
3299
}
3320
3300
3321
- void noteEndOfFieldOffsets (ClassDecl *whichClass) {
3322
- if (whichClass == Target)
3323
- return ;
3324
-
3325
- assert (InheritFieldOffsetVectors
3326
- && " no start of ancestor field offsets?!" );
3327
- }
3301
+ void noteEndOfFieldOffsets (ClassDecl *whichClass) {}
3328
3302
3329
3303
// Suppress GenericMetadataBuilderBase's default behavior of introducing
3330
3304
// fill ops for generic arguments unless they belong directly to the target
@@ -3338,7 +3312,6 @@ namespace {
3338
3312
// Lay out the field, but don't fill it in, we will copy it from
3339
3313
// the superclass.
3340
3314
HasDependentMetadata = true ;
3341
- InheritGenericParameters = true ;
3342
3315
ClassMetadataBuilderBase::addGenericArgument (type, forClass);
3343
3316
}
3344
3317
}
@@ -3353,7 +3326,6 @@ namespace {
3353
3326
// Lay out the field, but don't provide the fill op, which we'll get
3354
3327
// from the superclass.
3355
3328
HasDependentMetadata = true ;
3356
- InheritGenericParameters = true ;
3357
3329
ClassMetadataBuilderBase::addGenericWitnessTable (type, protocol,
3358
3330
forClass);
3359
3331
}
@@ -3446,15 +3418,13 @@ namespace {
3446
3418
IGF.Builder .CreateStore (rodata, rodataPtrSlot);
3447
3419
}
3448
3420
3449
- // If the field layout is dependent , ask the runtime to populate the
3450
- // offset vector.
3421
+ // If we have fields that are not fixed-size , ask the runtime to
3422
+ // populate the offset vector.
3451
3423
//
3452
- // FIXME: the right check here is if the class layout is dependent or
3453
- // resilient. Also if only the superclass is resilient, we can get away
3424
+ // FIXME: if only the superclass is resilient, we can get away
3454
3425
// with sliding field offsets instead of doing the entire layout all
3455
3426
// over again.
3456
- if (Target->isGenericContext () &&
3457
- HasDependentFieldOffsetVector) {
3427
+ if (!Layout.isFixedLayout ()) {
3458
3428
llvm::Value *fieldVector
3459
3429
= emitAddressOfFieldOffsetVectorInClassMetadata (IGF,
3460
3430
Target, metadata)
@@ -3505,18 +3475,19 @@ namespace {
3505
3475
{metadata, numFields,
3506
3476
firstField.getAddress (), fieldVector});
3507
3477
3508
- } else if (InheritFieldOffsetVectors || InheritGenericParameters) {
3478
+ } else {
3509
3479
// If we have any ancestor generic parameters or field offset vectors,
3510
3480
// copy them from the superclass metadata.
3511
3481
auto initFn = IGF.IGM .getInitializeSuperclassFn ();
3482
+
3483
+ bool copyFieldOffsetVectors = false ;
3484
+ if (FieldLayout.MetadataAccess != FieldAccess::ConstantDirect)
3485
+ copyFieldOffsetVectors = true ;
3486
+
3512
3487
IGF.Builder .CreateCall (initFn,
3513
3488
{metadata,
3514
3489
llvm::ConstantInt::get (IGF.IGM .Int1Ty ,
3515
- InheritFieldOffsetVectors)});
3516
- } else if (IGF.IGM .ObjCInterop ) {
3517
- // Register the class with the ObjC runtime.
3518
- llvm::Value *instantiateObjC = IGF.IGM .getInstantiateObjCClassFn ();
3519
- IGF.Builder .CreateCall (instantiateObjC, metadata);
3490
+ copyFieldOffsetVectors)});
3520
3491
}
3521
3492
}
3522
3493
0 commit comments