@@ -77,6 +77,7 @@ class PrintTypeInfo {
77
77
printField (" alignment" , TI.getAlignment ());
78
78
printField (" stride" , TI.getStride ());
79
79
printField (" num_extra_inhabitants" , TI.getNumExtraInhabitants ());
80
+ printField (" bitwise_takable" , TI.isBitwiseTakable ());
80
81
}
81
82
82
83
void printFields (const RecordTypeInfo &TI) {
@@ -190,8 +191,12 @@ void TypeInfo::dump(std::ostream &OS, unsigned Indent) const {
190
191
}
191
192
192
193
BuiltinTypeInfo::BuiltinTypeInfo (const BuiltinTypeDescriptor *descriptor)
193
- : TypeInfo(TypeInfoKind::Builtin, descriptor->Size , descriptor->Alignment,
194
- descriptor->Stride, descriptor->NumExtraInhabitants),
194
+ : TypeInfo(TypeInfoKind::Builtin,
195
+ descriptor->Size ,
196
+ descriptor->getAlignment (),
197
+ descriptor->Stride,
198
+ descriptor->NumExtraInhabitants,
199
+ descriptor->isBitwiseTakable()),
195
200
Name(descriptor->getMangledTypeName (0 )) {}
196
201
197
202
// / Utility class for building values that contain witness tables.
@@ -263,6 +268,29 @@ class ExistentialTypeInfoBuilder {
263
268
case FieldDescriptorKind::ClassProtocol:
264
269
Representation = ExistentialTypeRepresentation::Class;
265
270
WitnessTableCount++;
271
+
272
+ if (auto *Superclass = TC.getBuilder ().lookupSuperclass (P)) {
273
+ auto *SuperclassTI = TC.getTypeInfo (Superclass);
274
+ if (SuperclassTI == nullptr ) {
275
+ DEBUG_LOG (std::cerr << " No TypeInfo for superclass: " ;
276
+ Superclass->dump ());
277
+ Invalid = true ;
278
+ continue ;
279
+ }
280
+
281
+ if (!isa<ReferenceTypeInfo>(SuperclassTI)) {
282
+ DEBUG_LOG (std::cerr << " Superclass not a reference type: " ;
283
+ SuperclassTI->dump ());
284
+ Invalid = true ;
285
+ continue ;
286
+ }
287
+
288
+ if (cast<ReferenceTypeInfo>(SuperclassTI)->getReferenceCounting ()
289
+ == ReferenceCounting::Native) {
290
+ Refcounting = ReferenceCounting::Native;
291
+ }
292
+ }
293
+
266
294
continue ;
267
295
case FieldDescriptorKind::Protocol:
268
296
WitnessTableCount++;
@@ -397,9 +425,12 @@ class ExistentialTypeInfoBuilder {
397
425
398
426
// Non-class existentials consist of a three-word buffer,
399
427
// value metadata, and finally zero or more witness tables.
428
+ // The buffer is always bitwise takable, since non-bitwise
429
+ // takable payloads are stored out of line.
400
430
builder.addField (TI->getSize () * 3 ,
401
431
TI->getAlignment (),
402
- /* numExtraInhabitants=*/ 0 );
432
+ /* numExtraInhabitants=*/ 0 ,
433
+ /* bitwiseTakable=*/ true );
403
434
builder.addField (" metadata" , TC.getAnyMetatypeTypeRef ());
404
435
break ;
405
436
}
@@ -441,7 +472,8 @@ class ExistentialTypeInfoBuilder {
441
472
442
473
unsigned RecordTypeInfoBuilder::addField (unsigned fieldSize,
443
474
unsigned fieldAlignment,
444
- unsigned numExtraInhabitants) {
475
+ unsigned numExtraInhabitants,
476
+ bool bitwiseTakable) {
445
477
assert (fieldAlignment > 0 );
446
478
447
479
// Align the current size appropriately
@@ -456,6 +488,9 @@ unsigned RecordTypeInfoBuilder::addField(unsigned fieldSize,
456
488
// Update the aggregate alignment
457
489
Alignment = std::max (Alignment, fieldAlignment);
458
490
491
+ // The aggregate is bitwise takable if all elements are.
492
+ BitwiseTakable &= bitwiseTakable;
493
+
459
494
switch (Kind) {
460
495
// The extra inhabitants of a struct or tuple are the same as the extra
461
496
// inhabitants of the field that has the most.
@@ -500,7 +535,8 @@ void RecordTypeInfoBuilder::addField(const std::string &Name,
500
535
501
536
unsigned offset = addField (TI->getSize (),
502
537
TI->getAlignment (),
503
- TI->getNumExtraInhabitants ());
538
+ TI->getNumExtraInhabitants (),
539
+ TI->isBitwiseTakable ());
504
540
Fields.push_back ({Name, offset, TR, *TI});
505
541
}
506
542
@@ -515,7 +551,8 @@ const RecordTypeInfo *RecordTypeInfoBuilder::build() {
515
551
516
552
return TC.makeTypeInfo <RecordTypeInfo>(
517
553
Size , Alignment, Stride,
518
- NumExtraInhabitants, Kind, Fields);
554
+ NumExtraInhabitants, BitwiseTakable,
555
+ Kind, Fields);
519
556
}
520
557
521
558
const ReferenceTypeInfo *
@@ -548,13 +585,28 @@ TypeConverter::getReferenceTypeInfo(ReferenceKind Kind,
548
585
}
549
586
550
587
unsigned numExtraInhabitants = BuiltinTI->NumExtraInhabitants ;
551
- if (Kind == ReferenceKind::Weak)
588
+ bool bitwiseTakable = true ;
589
+
590
+ switch (Kind) {
591
+ case ReferenceKind::Strong:
592
+ break ;
593
+ case ReferenceKind::Weak:
552
594
numExtraInhabitants = 0 ;
595
+ bitwiseTakable = false ;
596
+ break ;
597
+ case ReferenceKind::Unowned:
598
+ if (Refcounting == ReferenceCounting::Unknown)
599
+ bitwiseTakable = false ;
600
+ break ;
601
+ case ReferenceKind::Unmanaged:
602
+ break ;
603
+ }
553
604
554
605
auto *TI = makeTypeInfo<ReferenceTypeInfo>(BuiltinTI->Size ,
555
- BuiltinTI->Alignment ,
606
+ BuiltinTI->getAlignment () ,
556
607
BuiltinTI->Stride ,
557
608
numExtraInhabitants,
609
+ bitwiseTakable,
558
610
Kind, Refcounting);
559
611
ReferenceCache[key] = TI;
560
612
return TI;
@@ -619,7 +671,12 @@ const TypeInfo *TypeConverter::getEmptyTypeInfo() {
619
671
if (EmptyTI != nullptr )
620
672
return EmptyTI;
621
673
622
- EmptyTI = makeTypeInfo<TypeInfo>(TypeInfoKind::Builtin, 0 , 1 , 1 , 0 );
674
+ EmptyTI = makeTypeInfo<TypeInfo>(TypeInfoKind::Builtin,
675
+ /* Size=*/ 0 ,
676
+ /* Alignment=*/ 1 ,
677
+ /* Stride=*/ 1 ,
678
+ /* ExtraInhabitants=*/ 0 ,
679
+ /* BitwiseTakable=*/ true );
623
680
return EmptyTI;
624
681
}
625
682
@@ -919,6 +976,7 @@ static unsigned getNumTagBytes(size_t size, unsigned emptyCases,
919
976
class EnumTypeInfoBuilder {
920
977
TypeConverter &TC;
921
978
unsigned Size , Alignment, NumExtraInhabitants;
979
+ bool BitwiseTakable;
922
980
RecordKind Kind;
923
981
std::vector<FieldInfo> Cases;
924
982
bool Invalid;
@@ -942,14 +1000,15 @@ class EnumTypeInfoBuilder {
942
1000
943
1001
Size = std::max (Size , TI->getSize ());
944
1002
Alignment = std::max (Alignment, TI->getAlignment ());
1003
+ BitwiseTakable &= TI->isBitwiseTakable ();
945
1004
946
1005
Cases.push_back ({Name, /* offset=*/ 0 , TR, *TI});
947
1006
}
948
1007
949
1008
public:
950
1009
EnumTypeInfoBuilder (TypeConverter &TC)
951
1010
: TC(TC), Size (0 ), Alignment(1 ), NumExtraInhabitants(0 ),
952
- Kind (RecordKind::Invalid), Invalid(false ) {}
1011
+ BitwiseTakable ( true ), Kind(RecordKind::Invalid), Invalid(false ) {}
953
1012
954
1013
const TypeInfo *
955
1014
build (const TypeRef *TR,
@@ -1028,8 +1087,9 @@ class EnumTypeInfoBuilder {
1028
1087
auto *FixedDescriptor = TC.getBuilder ().getBuiltinTypeInfo (TR);
1029
1088
if (FixedDescriptor) {
1030
1089
Size = FixedDescriptor->Size ;
1031
- Alignment = FixedDescriptor->Alignment ;
1090
+ Alignment = FixedDescriptor->getAlignment () ;
1032
1091
NumExtraInhabitants = FixedDescriptor->NumExtraInhabitants ;
1092
+ BitwiseTakable = FixedDescriptor->isBitwiseTakable ();
1033
1093
} else {
1034
1094
// Dynamic multi-payload enums do not have extra inhabitants
1035
1095
NumExtraInhabitants = 0 ;
@@ -1052,7 +1112,8 @@ class EnumTypeInfoBuilder {
1052
1112
1053
1113
return TC.makeTypeInfo <RecordTypeInfo>(
1054
1114
Size , Alignment, Stride,
1055
- NumExtraInhabitants, Kind, Cases);
1115
+ NumExtraInhabitants, BitwiseTakable,
1116
+ Kind, Cases);
1056
1117
}
1057
1118
};
1058
1119
@@ -1263,10 +1324,12 @@ class LowerType
1263
1324
// Destructure the existential and replace the "object"
1264
1325
// field with the right reference kind.
1265
1326
} else if (SubKind == RecordKind::ClassExistential) {
1327
+ bool BitwiseTakable = RecordTI->isBitwiseTakable ();
1266
1328
std::vector<FieldInfo> Fields;
1267
1329
for (auto &Field : RecordTI->getFields ()) {
1268
1330
if (Field.Name == " object" ) {
1269
1331
auto *FieldTI = rebuildStorageTypeInfo (&Field.TI , Kind);
1332
+ BitwiseTakable &= FieldTI->isBitwiseTakable ();
1270
1333
Fields.push_back ({Field.Name , Field.Offset , Field.TR , *FieldTI});
1271
1334
continue ;
1272
1335
}
@@ -1278,6 +1341,7 @@ class LowerType
1278
1341
RecordTI->getAlignment (),
1279
1342
RecordTI->getStride (),
1280
1343
RecordTI->getNumExtraInhabitants (),
1344
+ BitwiseTakable,
1281
1345
SubKind, Fields);
1282
1346
}
1283
1347
}
@@ -1354,7 +1418,10 @@ const TypeInfo *TypeConverter::getClassInstanceTypeInfo(const TypeRef *TR,
1354
1418
1355
1419
// Start layout from the given instance start offset. This should
1356
1420
// be the superclass instance size.
1357
- builder.addField (start, 1 , /* numExtraInhabitants=*/ 0 );
1421
+ builder.addField (/* size=*/ start,
1422
+ /* alignment=*/ 1 ,
1423
+ /* numExtraInhabitants=*/ 0 ,
1424
+ /* bitwiseTakable=*/ true );
1358
1425
1359
1426
for (auto Field : Fields)
1360
1427
builder.addField (Field.Name , Field.TR );
0 commit comments