@@ -251,7 +251,7 @@ BuiltinTypeInfo::BuiltinTypeInfo(unsigned Size, unsigned Alignment,
251
251
252
252
// Builtin.Int<N> is mangled as 'Bi' N '_'
253
253
// Returns 0 if this isn't an Int
254
- static unsigned isIntType (std::string name) {
254
+ static unsigned intTypeBitSize (std::string name) {
255
255
llvm::StringRef nameRef (name);
256
256
if (nameRef.starts_with (" Bi" ) && nameRef.endswith (" _" )) {
257
257
llvm::StringRef naturalRef = nameRef.drop_front (2 ).drop_back ();
@@ -274,11 +274,12 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
274
274
}
275
275
// If it has extra inhabitants, it could be an integer type with extra
276
276
// inhabitants (such as a bool) or a pointer.
277
- unsigned intSize = isIntType (Name);
277
+ unsigned intSize = intTypeBitSize (Name);
278
278
if (intSize > 0 ) {
279
279
// This is an integer type
280
280
281
- // If it cannot have extra inhabitants, return early...
281
+ // If extra inhabitants are impossible, return early...
282
+ // (assert in debug builds)
282
283
assert (intSize < getSize () * 8
283
284
&& " Standard-sized int cannot have extra inhabitants" );
284
285
if (intSize > 64 || getSize () > 8 || intSize >= getSize () * 8 ) {
@@ -319,14 +320,15 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
319
320
}
320
321
321
322
BitMask BuiltinTypeInfo::getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const {
322
- unsigned intSize = isIntType (Name);
323
+ unsigned intSize = intTypeBitSize (Name);
323
324
if (intSize > 0 ) {
324
325
// Odd-sized integers export spare bits
325
326
// In particular: bool fields are Int1 and export 7 spare bits
326
327
auto mask = BitMask::oneMask (getSize ());
327
328
mask.keepOnlyMostSignificantBits (getSize () * 8 - intSize);
328
329
return mask;
329
330
} else if (
331
+ Name == " ypXp" || // Any.Type
330
332
Name == " yyXf" // 'yyXf' = @thin () -> Void function
331
333
) {
332
334
// Builtin types that expose pointer spare bits
@@ -590,7 +592,9 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo {
590
592
}
591
593
592
594
BitMask getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const override {
593
- return BitMask::zeroMask (getSize ());
595
+ auto mask = BitMask (getSize (), maskForCount (getNumCases ()));
596
+ mask.complement ();
597
+ return mask;
594
598
}
595
599
596
600
bool projectEnumValue (remote::MemoryReader &reader,
@@ -660,7 +664,17 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo {
660
664
}
661
665
662
666
BitMask getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const override {
663
- return BitMask::zeroMask (getSize ());
667
+ FieldInfo PayloadCase = getCases ()[0 ];
668
+ size_t payloadSize = PayloadCase.TI .getSize ();
669
+ if (getSize () <= payloadSize) {
670
+ return BitMask::zeroMask (getSize ());
671
+ }
672
+ size_t tagSize = getSize () - payloadSize;
673
+ auto mask = BitMask::oneMask (getSize ());
674
+ mask.keepOnlyMostSignificantBits (tagSize * 8 ); // Clear payload bits
675
+ auto tagMaskUsedBits = BitMask (getSize (), maskForCount (getNumCases ()));
676
+ mask.andNotMask (tagMaskUsedBits, payloadSize); // Clear used tag bits
677
+ return mask;
664
678
}
665
679
666
680
// Think of a single-payload enum as being encoded in "pages".
@@ -1973,6 +1987,15 @@ class EnumTypeInfoBuilder {
1973
1987
default : Kind = EnumKind::MultiPayloadEnum; break ;
1974
1988
}
1975
1989
1990
+ // Sanity: Ignore any enum that claims to have a size more than 1MiB
1991
+ // This avoids allocating lots of memory for spare bit mask calculations
1992
+ // when clients try to interpret random chunks of memory as type descriptions.
1993
+ if (Size > (1024ULL * 1024 )) {
1994
+ unsigned Stride = ((Size + Alignment - 1 ) & ~(Alignment - 1 ));
1995
+ return TC.makeTypeInfo <UnsupportedEnumTypeInfo>(
1996
+ Size , Alignment, Stride, NumExtraInhabitants, BitwiseTakable, Kind, Cases);
1997
+ }
1998
+
1976
1999
if (Cases.size () == 1 ) {
1977
2000
if (EffectivePayloadCases == 0 ) {
1978
2001
// Zero-sized enum with only one empty case
@@ -2058,11 +2081,10 @@ class EnumTypeInfoBuilder {
2058
2081
//
2059
2082
2060
2083
// Do we have a fixed layout?
2061
- // TODO: Test whether a missing FixedDescriptor is actually relevant.
2062
2084
auto FixedDescriptor = TC.getBuilder ().getBuiltinTypeDescriptor (TR);
2063
2085
if (!FixedDescriptor || GenericPayloadCases > 0 ) {
2064
2086
// This is a "dynamic multi-payload enum". For example,
2065
- // this occurs with:
2087
+ // this occurs with generics such as :
2066
2088
// ```
2067
2089
// class ClassWithEnum<T> {
2068
2090
// enum E {
@@ -2072,6 +2094,12 @@ class EnumTypeInfoBuilder {
2072
2094
// var e: E?
2073
2095
// }
2074
2096
// ```
2097
+ // and when we have a resilient inner enum, such as:
2098
+ // ```
2099
+ // enum E2 {
2100
+ // case y(E1_resilient)
2101
+ // case z(Int)
2102
+ // }
2075
2103
auto tagCounts = getEnumTagCounts (Size , EffectiveNoPayloadCases,
2076
2104
EffectivePayloadCases);
2077
2105
Size += tagCounts.numTagBytes ;
@@ -2103,7 +2131,6 @@ class EnumTypeInfoBuilder {
2103
2131
unsigned Stride = ((Size + Alignment - 1 ) & ~(Alignment - 1 ));
2104
2132
if (Stride == 0 )
2105
2133
Stride = 1 ;
2106
- auto PayloadSize = EnumTypeInfo::getPayloadSizeForCases (Cases);
2107
2134
2108
2135
// Compute the spare bit mask and determine if we have any address-only fields
2109
2136
auto localSpareBitMask = BitMask::oneMask (Size );
@@ -2115,44 +2142,11 @@ class EnumTypeInfoBuilder {
2115
2142
}
2116
2143
}
2117
2144
2118
- // See if we have MPE bit mask information from the compiler...
2119
- // TODO: drop this?
2120
-
2121
- // Uncomment the following line to dump the MPE section every time we come through here...
2122
- // TC.getBuilder().dumpMultiPayloadEnumSection(std::cerr); // DEBUG helper
2123
-
2124
- auto MPEDescriptor = TC.getBuilder ().getMultiPayloadEnumDescriptor (TR);
2125
- if (MPEDescriptor && MPEDescriptor->usesPayloadSpareBits ()) {
2126
- // We found compiler-provided spare bit data...
2127
- auto PayloadSpareBitMaskByteCount = MPEDescriptor->getPayloadSpareBitMaskByteCount ();
2128
- auto PayloadSpareBitMaskByteOffset = MPEDescriptor->getPayloadSpareBitMaskByteOffset ();
2129
- auto SpareBitMask = MPEDescriptor->getPayloadSpareBits ();
2130
- BitMask compilerSpareBitMask (PayloadSize, SpareBitMask,
2131
- PayloadSpareBitMaskByteCount, PayloadSpareBitMaskByteOffset);
2132
-
2133
- if (compilerSpareBitMask.isZero () || hasAddrOnly) {
2134
- // If there are no spare bits, use the "simple" tag-only implementation.
2135
- return TC.makeTypeInfo <TaggedMultiPayloadEnumTypeInfo>(
2136
- Size , Alignment, Stride, NumExtraInhabitants,
2137
- BitwiseTakable, Cases, EffectivePayloadCases);
2138
- }
2139
-
2140
- #if 0 // TODO: This should be !defined(NDEBUG)
2141
- // Verify that compiler provided and local spare bit info agree...
2142
- // TODO: If we could make this actually work, then we wouldn't need the
2143
- // bulky compiler-provided info, would we?
2144
- assert(localSpareBitMask == compilerSpareBitMask);
2145
- #endif
2146
-
2147
- // Use compiler-provided spare bit information
2148
- return TC.makeTypeInfo <MultiPayloadEnumTypeInfo>(
2149
- Size , Alignment, Stride, NumExtraInhabitants,
2150
- BitwiseTakable, Cases, compilerSpareBitMask,
2151
- EffectivePayloadCases);
2152
- }
2153
-
2154
2145
if (localSpareBitMask.isZero () || hasAddrOnly) {
2155
- // Simple case that does not use spare bits
2146
+ // Simple tag-only layout does not use spare bits.
2147
+ // Either:
2148
+ // * There are no spare bits, or
2149
+ // * We can't copy it to strip spare bits.
2156
2150
return TC.makeTypeInfo <TaggedMultiPayloadEnumTypeInfo>(
2157
2151
Size , Alignment, Stride, NumExtraInhabitants,
2158
2152
BitwiseTakable, Cases, EffectivePayloadCases);
0 commit comments