@@ -5037,6 +5037,10 @@ namespace {
5037
5037
public:
5038
5038
void noteStartOfTypeSpecificMembers () {}
5039
5039
5040
+ SILType getLoweredType () {
5041
+ return IGM.getLoweredType (Target->getDeclaredTypeInContext ());
5042
+ }
5043
+
5040
5044
MetadataKind getMetadataKind () {
5041
5045
return MetadataKind::Struct;
5042
5046
}
@@ -5067,8 +5071,7 @@ namespace {
5067
5071
void addFieldOffset (VarDecl *var) {
5068
5072
assert (var->hasStorage () &&
5069
5073
" storing field offset for computed property?!" );
5070
- SILType structType =
5071
- IGM.getLoweredType (Target->getDeclaredTypeInContext ());
5074
+ SILType structType = getLoweredType ();
5072
5075
5073
5076
llvm::Constant *offset =
5074
5077
emitPhysicalStructMemberFixedOffset (IGM, structType, var);
@@ -5162,19 +5165,64 @@ namespace {
5162
5165
HasDependentVWT);
5163
5166
}
5164
5167
5165
- bool hasCompletionFunction () {
5166
- // TODO: recognize cases where this is not required
5168
+ bool hasExtraDataPattern () {
5169
+ auto &ti = IGM.getTypeInfo (getLoweredType ());
5170
+ if (!isa<FixedTypeInfo>(ti))
5171
+ return false ;
5172
+
5173
+ if (Target->getStoredProperties ().empty ())
5174
+ return false ;
5175
+
5167
5176
return true ;
5168
5177
}
5169
-
5178
+
5179
+ // / Fill in a constant field offset vector if possible.
5180
+ PartialPattern buildExtraDataPattern () {
5181
+ ConstantInitBuilder builder (IGM);
5182
+ auto init = builder.beginArray (IGM.SizeTy );
5183
+
5184
+ struct Scanner : StructMetadataScanner<Scanner> {
5185
+ SILType Type;
5186
+ ConstantArrayBuilder &B;
5187
+ Scanner (IRGenModule &IGM, StructDecl *target, SILType type,
5188
+ ConstantArrayBuilder &B)
5189
+ : StructMetadataScanner(IGM, target), Type(type), B(B) {}
5190
+
5191
+ void addFieldOffset (VarDecl *field) {
5192
+ auto offset = emitPhysicalStructMemberFixedOffset (IGM, Type, field);
5193
+ if (offset) {
5194
+ B.add (offset);
5195
+ return ;
5196
+ }
5197
+ assert (IGM.isKnownEmpty (Type.getFieldType (field, IGM.getSILModule ()),
5198
+ ResilienceExpansion::Maximal));
5199
+ B.addInt (IGM.SizeTy , 0 );
5200
+ }
5201
+ };
5202
+ Scanner (IGM, Target, getLoweredType (), init).layout ();
5203
+ Size vectorSize = init.getNextOffsetFromGlobal ();
5204
+
5205
+ auto global = init.finishAndCreateGlobal (" " , IGM.getPointerAlignment (),
5206
+ /* constant*/ true );
5207
+
5208
+ auto &layout = IGM.getMetadataLayout (Target);
5209
+ return { global,
5210
+ layout.getFieldOffsetVectorOffset ().getStatic ()
5211
+ - IGM.getOffsetOfStructTypeSpecificMetadataMembers (),
5212
+ vectorSize };
5213
+ }
5214
+
5215
+ bool hasCompletionFunction () {
5216
+ return !isa<FixedTypeInfo>(IGM.getTypeInfo (getLoweredType ()));
5217
+ }
5218
+
5170
5219
void emitInitializeMetadata (IRGenFunction &IGF,
5171
5220
llvm::Value *metadata,
5172
5221
bool isVWTMutable) {
5173
5222
// Nominal types are always preserved through SIL lowering.
5174
- auto structTy = Target->getDeclaredTypeInContext ()->getCanonicalType ();
5175
- IGM.getTypeInfoForUnlowered (structTy)
5176
- .initializeMetadata (IGF, metadata, isVWTMutable,
5177
- IGF.IGM .getLoweredType (structTy));
5223
+ auto loweredTy = getLoweredType ();
5224
+ IGM.getTypeInfo (loweredTy)
5225
+ .initializeMetadata (IGF, metadata, isVWTMutable, loweredTy);
5178
5226
}
5179
5227
};
5180
5228
} // end anonymous namespace
@@ -5231,6 +5279,10 @@ namespace {
5231
5279
: super(IGM, theEnum), B(B) {
5232
5280
}
5233
5281
5282
+ SILType getLoweredType () {
5283
+ return IGM.getLoweredType (Target->getDeclaredTypeInContext ());
5284
+ }
5285
+
5234
5286
public:
5235
5287
void noteStartOfTypeSpecificMembers () {}
5236
5288
@@ -5270,6 +5322,19 @@ namespace {
5270
5322
void addGenericWitnessTable (CanType type, ProtocolConformanceRef conf) {
5271
5323
B.addNullPointer (IGM.WitnessTablePtrTy );
5272
5324
}
5325
+
5326
+ Optional<Size> getConstantPayloadSize () {
5327
+ auto enumTy = Target->getDeclaredTypeInContext ()->getCanonicalType ();
5328
+ auto &enumTI = IGM.getTypeInfoForUnlowered (enumTy);
5329
+ if (!enumTI.isFixedSize (ResilienceExpansion::Maximal)) {
5330
+ return None;
5331
+ }
5332
+
5333
+ assert (!enumTI.isFixedSize (ResilienceExpansion::Minimal) &&
5334
+ " non-generic, non-resilient enums don't need payload size in metadata" );
5335
+ auto &strategy = getEnumImplStrategy (IGM, enumTy);
5336
+ return Size (strategy.getPayloadSizeForMetadata ());
5337
+ }
5273
5338
};
5274
5339
5275
5340
class EnumMetadataBuilder
@@ -5281,19 +5346,17 @@ namespace {
5281
5346
ConstantStructBuilder &B)
5282
5347
: EnumMetadataBuilderBase(IGM, theEnum, B) {}
5283
5348
5349
+
5350
+
5284
5351
void addPayloadSize () {
5285
- auto enumTy = Target->getDeclaredTypeInContext ()->getCanonicalType ();
5286
- auto &enumTI = IGM.getTypeInfoForUnlowered (enumTy);
5287
- if (!enumTI.isFixedSize (ResilienceExpansion::Maximal)) {
5352
+ auto payloadSize = getConstantPayloadSize ();
5353
+ if (!payloadSize) {
5288
5354
B.addInt (IGM.IntPtrTy , 0 );
5289
5355
HasUnfilledPayloadSize = true ;
5290
5356
return ;
5291
5357
}
5292
5358
5293
- assert (!enumTI.isFixedSize (ResilienceExpansion::Minimal) &&
5294
- " non-generic, non-resilient enums don't need payload size in metadata" );
5295
- auto &strategy = getEnumImplStrategy (IGM, enumTy);
5296
- B.addInt (IGM.IntPtrTy , strategy.getPayloadSizeForMetadata ());
5359
+ B.addInt (IGM.IntPtrTy , payloadSize->getValue ());
5297
5360
}
5298
5361
5299
5362
bool canBeConstant () {
@@ -5325,9 +5388,24 @@ namespace {
5325
5388
- IGM.getOffsetOfEnumTypeSpecificMetadataMembers ();
5326
5389
auto extraSizeV = IGM.getSize (extraSize);
5327
5390
5328
- return IGF.Builder .CreateCall (IGM.getAllocateGenericValueMetadataFn (),
5329
- {descriptor, arguments, templatePointer,
5330
- extraSizeV});
5391
+ auto metadata =
5392
+ IGF.Builder .CreateCall (IGM.getAllocateGenericValueMetadataFn (),
5393
+ {descriptor, arguments, templatePointer,
5394
+ extraSizeV});
5395
+
5396
+ // Initialize the payload-size field if we have a constant value for it.
5397
+ // This is so small that we just do it inline instead of bothering
5398
+ // with a pattern.
5399
+ if (layout.hasPayloadSizeOffset ()) {
5400
+ if (auto size = getConstantPayloadSize ()) {
5401
+ auto offset = layout.getPayloadSizeOffset ();
5402
+ auto slot = IGF.emitAddressAtOffset (metadata, offset, IGM.SizeTy ,
5403
+ IGM.getPointerAlignment ());
5404
+ IGF.Builder .CreateStore (IGM.getSize (*size), slot);
5405
+ }
5406
+ }
5407
+
5408
+ return metadata;
5331
5409
}
5332
5410
5333
5411
llvm::Constant *emitValueWitnessTable () {
@@ -5336,18 +5414,16 @@ namespace {
5336
5414
}
5337
5415
5338
5416
bool hasCompletionFunction () {
5339
- // TODO: recognize cases where this is not required
5340
- return true ;
5417
+ return !isa<FixedTypeInfo>(IGM.getTypeInfo (getLoweredType ()));
5341
5418
}
5342
5419
5343
5420
void emitInitializeMetadata (IRGenFunction &IGF,
5344
5421
llvm::Value *metadata,
5345
5422
bool isVWTMutable) {
5346
5423
// Nominal types are always preserved through SIL lowering.
5347
- auto enumTy = Target->getDeclaredTypeInContext ()->getCanonicalType ();
5348
- IGM.getTypeInfoForUnlowered (enumTy)
5349
- .initializeMetadata (IGF, metadata, isVWTMutable,
5350
- IGF.IGM .getLoweredType (enumTy));
5424
+ auto enumTy = getLoweredType ();
5425
+ IGM.getTypeInfo (enumTy)
5426
+ .initializeMetadata (IGF, metadata, isVWTMutable, enumTy);
5351
5427
}
5352
5428
};
5353
5429
0 commit comments