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:
Jordan Rose
2017-09-21 17:55:37 -07:00
parent 00361df52b
commit 7e3aaff78d
3 changed files with 34 additions and 8 deletions

View File

@@ -2286,9 +2286,11 @@ bool NominalTypeDecl::isFormallyResilient() const {
/*respectVersionedAttr=*/true).isPublic())
return false;
// Check for an explicit @_fixed_layout attribute.
if (getAttrs().hasAttribute<FixedLayoutAttr>())
// Check for an explicit @_fixed_layout or @_frozen attribute.
if (getAttrs().hasAttribute<FixedLayoutAttr>() ||
getAttrs().hasAttribute<FrozenAttr>()) {
return false;
}
// Structs and enums imported from C *always* have a fixed layout.
// We know their size, and pass them as values in SIL and IRGen.

View File

@@ -38,7 +38,7 @@ public struct Reference {
public var n: Class
}
@_fixed_layout public enum Either {
@_frozen public enum Either {
case Left(Reference)
case Right(Reference)
}
@@ -57,7 +57,7 @@ enum InternalEither {
public var n: Class
}
@_fixed_layout public enum EitherFast {
@_frozen public enum EitherFast {
case Left(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: call void @swift_initEnumMetadataMultiPayload(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 2, i8*** {{.*}})

View File

@@ -1,24 +1,29 @@
import resilient_struct
// Fixed-layout enum with resilient members
@_fixed_layout @_frozen public enum SimpleShape {
@_frozen public enum SimpleShape {
case KleinBottle
case Triangle(Size)
}
// Fixed-layout enum with resilient members
@_fixed_layout @_frozen public enum Shape {
@_frozen public enum Shape {
case Point
case Rect(Size)
case RoundedRect(Size, Size)
}
// Fixed-layout enum with indirect resilient members
@_fixed_layout @_frozen public enum FunnyShape {
@_frozen public enum FunnyShape {
indirect case Parallelogram(Size)
indirect case Trapezoid(Size)
}
@_frozen public enum FullyFixedLayout {
case noPayload
case hasPayload(Int)
}
// The enum payload has fixed layout inside this module, but
// resilient layout outside. Make sure we emit the payload
// size in the metadata.
@@ -33,7 +38,7 @@ public struct Color {
}
}
@_fixed_layout @_frozen public enum CustomColor {
@_frozen public enum CustomColor {
case Black
case White
case Custom(Color)