@@ -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.endswith (" _" )) {
257257 llvm::StringRef naturalRef = nameRef.drop_front (2 ).drop_back ();
@@ -274,11 +274,12 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
274274 }
275275 // If it has extra inhabitants, it could be an integer type with extra
276276 // inhabitants (such as a bool) or a pointer.
277- unsigned intSize = isIntType (Name);
277+ unsigned intSize = intTypeBitSize (Name);
278278 if (intSize > 0 ) {
279279 // This is an integer type
280280
281- // If it cannot have extra inhabitants, return early...
281+ // If extra inhabitants are impossible, return early...
282+ // (assert in debug builds)
282283 assert (intSize < getSize () * 8
283284 && " Standard-sized int cannot have extra inhabitants" );
284285 if (intSize > 64 || getSize () > 8 || intSize >= getSize () * 8 ) {
@@ -319,14 +320,15 @@ bool BuiltinTypeInfo::readExtraInhabitantIndex(
319320}
320321
321322BitMask BuiltinTypeInfo::getSpareBits (TypeConverter &TC, bool &hasAddrOnly) const {
322- unsigned intSize = isIntType (Name);
323+ unsigned intSize = intTypeBitSize (Name);
323324 if (intSize > 0 ) {
324325 // Odd-sized integers export spare bits
325326 // In particular: bool fields are Int1 and export 7 spare bits
326327 auto mask = BitMask::oneMask (getSize ());
327328 mask.keepOnlyMostSignificantBits (getSize () * 8 - intSize);
328329 return mask;
329330 } else if (
331+ Name == " ypXp" || // Any.Type
330332 Name == " yyXf" // 'yyXf' = @thin () -> Void function
331333 ) {
332334 // Builtin types that expose pointer spare bits
@@ -590,7 +592,9 @@ class NoPayloadEnumTypeInfo: public EnumTypeInfo {
590592 }
591593
592594 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;
594598 }
595599
596600 bool projectEnumValue (remote::MemoryReader &reader,
@@ -660,7 +664,17 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo {
660664 }
661665
662666 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;
664678 }
665679
666680 // Think of a single-payload enum as being encoded in "pages".
@@ -1973,6 +1987,15 @@ class EnumTypeInfoBuilder {
19731987 default : Kind = EnumKind::MultiPayloadEnum; break ;
19741988 }
19751989
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+
19761999 if (Cases.size () == 1 ) {
19772000 if (EffectivePayloadCases == 0 ) {
19782001 // Zero-sized enum with only one empty case
@@ -2058,11 +2081,10 @@ class EnumTypeInfoBuilder {
20582081 //
20592082
20602083 // Do we have a fixed layout?
2061- // TODO: Test whether a missing FixedDescriptor is actually relevant.
20622084 auto FixedDescriptor = TC.getBuilder ().getBuiltinTypeDescriptor (TR);
20632085 if (!FixedDescriptor || GenericPayloadCases > 0 ) {
20642086 // This is a "dynamic multi-payload enum". For example,
2065- // this occurs with:
2087+ // this occurs with generics such as :
20662088 // ```
20672089 // class ClassWithEnum<T> {
20682090 // enum E {
@@ -2072,6 +2094,12 @@ class EnumTypeInfoBuilder {
20722094 // var e: E?
20732095 // }
20742096 // ```
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+ // }
20752103 auto tagCounts = getEnumTagCounts (Size, EffectiveNoPayloadCases,
20762104 EffectivePayloadCases);
20772105 Size += tagCounts.numTagBytes ;
@@ -2103,7 +2131,6 @@ class EnumTypeInfoBuilder {
21032131 unsigned Stride = ((Size + Alignment - 1 ) & ~(Alignment - 1 ));
21042132 if (Stride == 0 )
21052133 Stride = 1 ;
2106- auto PayloadSize = EnumTypeInfo::getPayloadSizeForCases (Cases);
21072134
21082135 // Compute the spare bit mask and determine if we have any address-only fields
21092136 auto localSpareBitMask = BitMask::oneMask (Size);
@@ -2115,44 +2142,11 @@ class EnumTypeInfoBuilder {
21152142 }
21162143 }
21172144
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-
21542145 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.
21562150 return TC.makeTypeInfo <TaggedMultiPayloadEnumTypeInfo>(
21572151 Size, Alignment, Stride, NumExtraInhabitants,
21582152 BitwiseTakable, Cases, EffectivePayloadCases);
0 commit comments