@@ -251,7 +251,7 @@ BuiltinTypeInfo::BuiltinTypeInfo(unsigned Size, unsigned Alignment,
251251
252252// Builtin.Int<N> is mangled as 'Bi' N '_'
253253// Returns 0 if this isn't an Int
254- static unsigned isIntType (std::string name) {
254+ static unsigned intTypeBitSize (std::string name) {
255255 llvm::StringRef nameRef (name);
256256 if (nameRef.starts_with (" Bi" ) && nameRef.ends_with (" _" )) {
257257 llvm::StringRef naturalRef = nameRef.drop_front (2 ).drop_back ();
@@ -272,23 +272,36 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
272272 *extraInhabitantIndex = -1 ;
273273 return true ;
274274 }
275- unsigned intSize = isIntType (Name);
276- if (intSize > 0 && intSize < 64 && getSize () <= 8 && intSize < getSize () * 8 ) {
275+ // If it has extra inhabitants, it could be an integer type with extra
276+ // inhabitants (such as a bool) or a pointer.
277+ unsigned intSize = intTypeBitSize (Name);
278+ if (intSize > 0 ) {
279+ // This is an integer type
280+
281+ // If extra inhabitants are impossible, return early...
282+ // (assert in debug builds)
283+ assert (intSize < getSize () * 8
284+ && " Standard-sized int cannot have extra inhabitants" );
285+ if (intSize > 64 || getSize () > 8 || intSize >= getSize () * 8 ) {
286+ *extraInhabitantIndex = -1 ;
287+ return true ;
288+ }
289+
290+ // Compute range of extra inhabitants
277291 uint64_t maxValidValue = (((uint64_t )1 ) << intSize) - 1 ;
278292 uint64_t maxAvailableValue = (((uint64_t )1 ) << (getSize () * 8 )) - 1 ;
279293 uint64_t computedExtraInhabitants = maxAvailableValue - maxValidValue;
280294 if (computedExtraInhabitants > ValueWitnessFlags::MaxNumExtraInhabitants) {
281295 computedExtraInhabitants = ValueWitnessFlags::MaxNumExtraInhabitants;
282296 }
283297 assert (getNumExtraInhabitants () == computedExtraInhabitants &&
284- " Unexpected number of extra inhabitants in an odd-sized integer" );
298+ " Unexpected number of extra inhabitants in an odd-sized integer" );
285299
300+ // Example: maxValidValue is 1 for a 1-bit bool, so any larger value
301+ // is an extra inhabitant.
286302 uint64_t rawValue;
287303 if (!reader.readInteger (address, getSize (), &rawValue))
288304 return false ;
289-
290- // Example: maxValidValue is 1 for a 1-bit bool, so any larger value
291- // is an extra inhabitant.
292305 if (maxValidValue < rawValue) {
293306 *extraInhabitantIndex = rawValue - maxValidValue - 1 ;
294307 } else {
@@ -307,14 +320,15 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
307320}
308321
309322BitMask BuiltinTypeInfo::getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const {
310- unsigned intSize = isIntType (Name);
323+ unsigned intSize = intTypeBitSize (Name);
311324 if (intSize > 0 ) {
312325 // Odd-sized integers export spare bits
313326 // In particular: bool fields are Int1 and export 7 spare bits
314327 auto mask = BitMask::oneMask (getSize ());
315328 mask.keepOnlyMostSignificantBits (getSize () * 8 - intSize);
316329 return mask;
317330 } else if (
331+ Name == " ypXp" || // Any.Type
318332 Name == " yyXf" // 'yyXf' = @thin () -> Void function
319333 ) {
320334 // Builtin types that expose pointer spare bits
@@ -578,7 +592,9 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo {
578592 }
579593
580594 BitMask getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const override {
581- return BitMask::zeroMask (getSize ());
595+ auto mask = BitMask (getSize (), maskForCount (getNumCases ()));
596+ mask.complement ();
597+ return mask;
582598 }
583599
584600 bool projectEnumValue (remote::MemoryReader &reader,
@@ -648,7 +664,17 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo {
648664 }
649665
650666 BitMask getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const override {
651- 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;
652678 }
653679
654680 // Think of a single-payload enum as being encoded in "pages".
@@ -1961,6 +1987,15 @@ class EnumTypeInfoBuilder {
19611987 default : Kind = EnumKind::MultiPayloadEnum; break ;
19621988 }
19631989
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+
19641999 if (Cases.size () == 1 ) {
19652000 if (EffectivePayloadCases == 0 ) {
19662001 // Zero-sized enum with only one empty case
@@ -2046,11 +2081,10 @@ class EnumTypeInfoBuilder {
20462081 //
20472082
20482083 // Do we have a fixed layout?
2049- // TODO: Test whether a missing FixedDescriptor is actually relevant.
20502084 auto FixedDescriptor = TC.getBuilder ().getBuiltinTypeDescriptor (TR);
20512085 if (!FixedDescriptor || GenericPayloadCases > 0 ) {
20522086 // This is a "dynamic multi-payload enum". For example,
2053- // this occurs with:
2087+ // this occurs with generics such as :
20542088 // ```
20552089 // class ClassWithEnum<T> {
20562090 // enum E {
@@ -2060,6 +2094,12 @@ class EnumTypeInfoBuilder {
20602094 // var e: E?
20612095 // }
20622096 // ```
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+ // }
20632103 auto tagCounts = getEnumTagCounts (Size, EffectiveNoPayloadCases,
20642104 EffectivePayloadCases);
20652105 Size += tagCounts.numTagBytes ;
@@ -2091,7 +2131,6 @@ class EnumTypeInfoBuilder {
20912131 unsigned Stride = ((Size + Alignment - 1 ) & ~(Alignment - 1 ));
20922132 if (Stride == 0 )
20932133 Stride = 1 ;
2094- auto PayloadSize = EnumTypeInfo::getPayloadSizeForCases (Cases);
20952134
20962135 // Compute the spare bit mask and determine if we have any address-only fields
20972136 auto localSpareBitMask = BitMask::oneMask (Size);
@@ -2103,44 +2142,11 @@ class EnumTypeInfoBuilder {
21032142 }
21042143 }
21052144
2106- // See if we have MPE bit mask information from the compiler...
2107- // TODO: drop this?
2108-
2109- // Uncomment the following line to dump the MPE section every time we come through here...
2110- // TC.getBuilder().dumpMultiPayloadEnumSection(std::cerr); // DEBUG helper
2111-
2112- auto MPEDescriptor = TC.getBuilder ().getMultiPayloadEnumDescriptor (TR);
2113- if (MPEDescriptor && MPEDescriptor->usesPayloadSpareBits ()) {
2114- // We found compiler-provided spare bit data...
2115- auto PayloadSpareBitMaskByteCount = MPEDescriptor->getPayloadSpareBitMaskByteCount ();
2116- auto PayloadSpareBitMaskByteOffset = MPEDescriptor->getPayloadSpareBitMaskByteOffset ();
2117- auto SpareBitMask = MPEDescriptor->getPayloadSpareBits ();
2118- BitMask compilerSpareBitMask (PayloadSize, SpareBitMask,
2119- PayloadSpareBitMaskByteCount, PayloadSpareBitMaskByteOffset);
2120-
2121- if (compilerSpareBitMask.isZero () || hasAddrOnly) {
2122- // If there are no spare bits, use the "simple" tag-only implementation.
2123- return TC.makeTypeInfo <TaggedMultiPayloadEnumTypeInfo>(
2124- Size, Alignment, Stride, NumExtraInhabitants,
2125- BitwiseTakable, Cases, EffectivePayloadCases);
2126- }
2127-
2128- #if 0 // TODO: This should be !defined(NDEBUG)
2129- // Verify that compiler provided and local spare bit info agree...
2130- // TODO: If we could make this actually work, then we wouldn't need the
2131- // bulky compiler-provided info, would we?
2132- assert(localSpareBitMask == compilerSpareBitMask);
2133- #endif
2134-
2135- // Use compiler-provided spare bit information
2136- return TC.makeTypeInfo <MultiPayloadEnumTypeInfo>(
2137- Size, Alignment, Stride, NumExtraInhabitants,
2138- BitwiseTakable, Cases, compilerSpareBitMask,
2139- EffectivePayloadCases);
2140- }
2141-
21422145 if (localSpareBitMask.isZero () || hasAddrOnly) {
2143- // 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.
21442150 return TC.makeTypeInfo <TaggedMultiPayloadEnumTypeInfo>(
21452151 Size, Alignment, Stride, NumExtraInhabitants,
21462152 BitwiseTakable, Cases, EffectivePayloadCases);
0 commit comments