mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Treat exhaustive enums as "non-resilient", and add a few more tests
"Formally non-resilient" in this new world means "the enum has a fixed representation", which implies a fixed layout algorithm. We're not there yet, but non-exhaustive enums should be able to be fixed-layout as well by picking a general representation that won't need to grow. Specifically, that's enums with raw types, and possibly also indirect enums as well. (It's likely the '_fixed_layout' /attribute/ on enums will go away, but the concept of a fixed-layout enum is still useful.)
This commit is contained in:
@@ -2286,9 +2286,11 @@ bool NominalTypeDecl::isFormallyResilient() const {
|
|||||||
/*respectVersionedAttr=*/true).isPublic())
|
/*respectVersionedAttr=*/true).isPublic())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check for an explicit @_fixed_layout attribute.
|
// Check for an explicit @_fixed_layout or @_frozen attribute.
|
||||||
if (getAttrs().hasAttribute<FixedLayoutAttr>())
|
if (getAttrs().hasAttribute<FixedLayoutAttr>() ||
|
||||||
|
getAttrs().hasAttribute<FrozenAttr>()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Structs and enums imported from C *always* have a fixed layout.
|
// Structs and enums imported from C *always* have a fixed layout.
|
||||||
// We know their size, and pass them as values in SIL and IRGen.
|
// We know their size, and pass them as values in SIL and IRGen.
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public struct Reference {
|
|||||||
public var n: Class
|
public var n: Class
|
||||||
}
|
}
|
||||||
|
|
||||||
@_fixed_layout public enum Either {
|
@_frozen public enum Either {
|
||||||
case Left(Reference)
|
case Left(Reference)
|
||||||
case Right(Reference)
|
case Right(Reference)
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ enum InternalEither {
|
|||||||
public var n: Class
|
public var n: Class
|
||||||
}
|
}
|
||||||
|
|
||||||
@_fixed_layout public enum EitherFast {
|
@_frozen public enum EitherFast {
|
||||||
case Left(ReferenceFast)
|
case Left(ReferenceFast)
|
||||||
case Right(ReferenceFast)
|
case Right(ReferenceFast)
|
||||||
}
|
}
|
||||||
@@ -263,6 +263,25 @@ extension ResilientMultiPayloadGenericEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience39constructExhaustiveWithResilientMembers010resilient_A011SimpleShapeOyF"(%T14resilient_enum11SimpleShapeO* noalias nocapture sret)
|
||||||
|
// CHECK: [[BUFFER:%.*]] = bitcast %T14resilient_enum11SimpleShapeO* %0 to %swift.opaque*
|
||||||
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$S16resilient_struct4SizeVMa"([[INT]] 0)
|
||||||
|
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
||||||
|
// CHECK: [[STORE_TAG:%.*]] = bitcast i8* {{%.+}} to void (%swift.opaque*, i32, i32, %swift.type*)*
|
||||||
|
// CHECK-NEXT: call void [[STORE_TAG]](%swift.opaque* noalias [[BUFFER]], i32 0, i32 1, %swift.type* [[METADATA]])
|
||||||
|
// CHECK-NEXT: ret void
|
||||||
|
// CHECK-NEXT: {{^}$}}
|
||||||
|
public func constructExhaustiveWithResilientMembers() -> SimpleShape {
|
||||||
|
return .KleinBottle
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{( protected)?}} swiftcc { i{{64|32}}, i8 } @"$S15enum_resilience19constructFullyFixed010resilient_A00dE6LayoutOyF"()
|
||||||
|
// CHECK: ret { [[INT]], i8 } { [[INT]] 0, i8 1 }
|
||||||
|
// CHECK-NEXT: {{^}$}}
|
||||||
|
public func constructFullyFixed() -> FullyFixedLayout {
|
||||||
|
return .noPayload
|
||||||
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_EnumWithResilientPayload(i8*)
|
// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_EnumWithResilientPayload(i8*)
|
||||||
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 2, i8*** {{.*}})
|
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 2, i8*** {{.*}})
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,29 @@
|
|||||||
import resilient_struct
|
import resilient_struct
|
||||||
|
|
||||||
// Fixed-layout enum with resilient members
|
// Fixed-layout enum with resilient members
|
||||||
@_fixed_layout @_frozen public enum SimpleShape {
|
@_frozen public enum SimpleShape {
|
||||||
case KleinBottle
|
case KleinBottle
|
||||||
case Triangle(Size)
|
case Triangle(Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixed-layout enum with resilient members
|
// Fixed-layout enum with resilient members
|
||||||
@_fixed_layout @_frozen public enum Shape {
|
@_frozen public enum Shape {
|
||||||
case Point
|
case Point
|
||||||
case Rect(Size)
|
case Rect(Size)
|
||||||
case RoundedRect(Size, Size)
|
case RoundedRect(Size, Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixed-layout enum with indirect resilient members
|
// Fixed-layout enum with indirect resilient members
|
||||||
@_fixed_layout @_frozen public enum FunnyShape {
|
@_frozen public enum FunnyShape {
|
||||||
indirect case Parallelogram(Size)
|
indirect case Parallelogram(Size)
|
||||||
indirect case Trapezoid(Size)
|
indirect case Trapezoid(Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@_frozen public enum FullyFixedLayout {
|
||||||
|
case noPayload
|
||||||
|
case hasPayload(Int)
|
||||||
|
}
|
||||||
|
|
||||||
// The enum payload has fixed layout inside this module, but
|
// The enum payload has fixed layout inside this module, but
|
||||||
// resilient layout outside. Make sure we emit the payload
|
// resilient layout outside. Make sure we emit the payload
|
||||||
// size in the metadata.
|
// size in the metadata.
|
||||||
@@ -33,7 +38,7 @@ public struct Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@_fixed_layout @_frozen public enum CustomColor {
|
@_frozen public enum CustomColor {
|
||||||
case Black
|
case Black
|
||||||
case White
|
case White
|
||||||
case Custom(Color)
|
case Custom(Color)
|
||||||
|
|||||||
Reference in New Issue
Block a user