// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime-%target-ptrsize // REQUIRES: CPU=i386 || CPU=x86_64 // We have to claim this is raw SIL because there are critical edges from non // cond_br instructions. sil_stage raw import Builtin import Swift // -- Singleton enum. The representation is just the singleton payload. // CHECK: %T4enum9SingletonO = type <{ <{ i64, i64 }> }> // -- Singleton enum with heap object ref payload. // CHECK: %T4enum12SingletonRefO = type <{ %swift.refcounted* }> // -- No-payload enums. The representation is just an enum tag. // CHECK: %T4enum10NoPayloadsO = type <{ i8 }> // CHECK: %T4enum11NoPayloads2O = type <{ i8 }> // -- Single-payload enum, no extra inhabitants in the payload type. The // representation adds a tag bit to distinguish payload from enum tag: // case x(i64): X0 X1 X2 ... X63 | 0, where X0...X63 are the payload bits // case y: 0 0 0 ... 0 | 1 // case z: 1 0 0 ... 0 | 1 // CHECK-64: %T4enum17SinglePayloadNoXIO = type <{ [8 x i8], [1 x i8] }> // CHECK-64: %T4enum18SinglePayloadNoXI2O = type <{ [8 x i8], [1 x i8] }> // CHECK-32: %T4enum17SinglePayloadNoXIO = type <{ [4 x i8], [1 x i8] }> // CHECK-32: %T4enum18SinglePayloadNoXI2O = type <{ [4 x i8], [1 x i8] }> // -- Single-payload enum, spare bits. The representation uses a tag bit // out of the payload to distinguish payload from enum tag: // case x(i3): X0 X1 X2 0 0 0 0 0 // case y: 0 0 0 1 0 0 0 0 // case z: 1 0 0 1 0 0 0 0 // CHECK: %T4enum21SinglePayloadSpareBitO = type <{ [8 x i8] }> // -- Single-payload enum containing a no-payload enum as its payload. // The representation takes extra inhabitants starting after the greatest // discriminator value used by the nested no-payload enum. // CHECK: %T4enum19SinglePayloadNestedO = type <{ [1 x i8] }> // -- Single-payload enum containing another single-payload enum as its // payload. // The representation takes extra inhabitants from the nested enum's payload // that were unused by the nested enum. // CHECK: %T4enum019SinglePayloadNestedD0O = type <{ [1 x i8] }> // -- Multi-payload enum, no spare bits. The representation adds tag bits // to discriminate payloads. No-payload cases all share a tag. // case x(i8): X0 X1 X2 ... X7 X8 | 0 0 // case y(i7): Y0 Y1 Y2 ... Y7 0 | 1 0 // case z(i2): Z0 Z1 0 ... 0 0 | 0 1 // case a: 0 0 0 ... 0 0 | 1 1 // case b: 1 0 0 ... 0 0 | 1 1 // case c: 0 1 0 ... 0 0 | 1 1 // CHECK: %T4enum23MultiPayloadNoSpareBitsO = type <{ [8 x i8], [1 x i8] }> // -- Multi-payload enum, one spare bit. The representation uses spare bits // common to all payloads to partially discriminate payloads, with added // tag bits to cover the gap. No-payload cases all share a tag. // case x(i7): X0 X1 X2 X3 X4 X5 X6 0 | 0 // case y(i1): Y 0 0 0 0 0 0 1 | 0 // case z(i5): Z0 Z1 Z2 Z3 Z4 0 0 0 | 1 // case a: 0 0 0 0 0 0 0 1 | 1 // case b: 1 0 0 0 0 0 0 1 | 1 // case c: 0 1 0 0 0 0 0 1 | 1 // CHECK: %T4enum23MultiPayloadOneSpareBitO = type <{ [8 x i8], [1 x i8] }> // -- Multi-payload enum, two spare bits. Same as above, except we have enough // spare bits not to require any added tag bits. // case x(i6): X0 X1 X2 X3 X4 X5 0 0 // case y(i1): Y 0 0 0 0 0 1 0 // case z(i5): Z0 Z1 Z2 Z3 Z4 0 0 1 // case a: 0 0 0 0 0 0 1 1 // case b: 1 0 0 0 0 0 1 1 // case c: 0 1 0 0 0 0 1 1 // CHECK: %T4enum24MultiPayloadTwoSpareBitsO = type <{ [8 x i8] }> // CHECK-64: %T4enum30MultiPayloadSpareBitAggregatesO = type <{ [16 x i8] }> // CHECK-64: %T4enum18MultiPayloadNestedO = type <{ [9 x i8] }> // CHECK-32: %T4enum18MultiPayloadNestedO = type <{ [5 x i8] }> // 32-bit object references don't have enough spare bits. // CHECK-64: %T4enum27MultiPayloadNestedSpareBitsO = type <{ [8 x i8] }> // -- Dynamic enums. The type layout is opaque; we dynamically bitcast to // the element type. // CHECK: %T4enum20DynamicSinglePayloadO = type <{}> // CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%T4enum20DynamicSinglePayloadOyytG]] = type <{ [1 x i8] }> // -- Address-only multi-payload enums. We can't use spare bits. // CHECK-64: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [16 x i8], [1 x i8] }> // CHECK-32: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [8 x i8], [1 x i8] }> // CHECK: [[DYNAMIC_SINGLETON:%T4enum16DynamicSingletonO.*]] = type <{}> // CHECK: %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO = type <{ [1 x i8], [1 x i8] }> // -- Dynamic metadata template carries a value witness table pattern // we fill in on instantiation. // The witness table pattern includes extra inhabitant witness // implementations which are used if the instance has extra inhabitants. // FIXME: Strings should be unnamed_addr. rdar://problem/22674524 // CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00" // CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [25 x i8] c"4enum16DynamicSingletonO\00" // CHECK: @_T04enum16DynamicSingletonOMn = hidden constant <{ {{.*}} i32 }> <{ // CHECK-SAME: [25 x i8]* [[DYNAMICSINGLETON_NAME]] // -- One payload // CHECK-SAME: i32 1, // -- No empty cases // CHECK-SAME: i32 0, // -- Case names // CHECK-SAME: [[DYNAMICSINGLETON_FIELD_NAMES]] // -- Case type accessor // CHECK-SAME: @get_field_types_DynamicSingleton // -- generic parameter vector offset // CHECK-SAME: i32 2, // -- generic parameter vector length; witness table counts // CHECK-SAME: i32 1, i32 1 // -- nesting depth // CHECK-SAME: i16 1 // -- flags // CHECK-SAME: i16 0 // -- generic parameters at depth 0 // CHECK-SAME: i32 1 // CHECK-SAME: }> // CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, [18 x i8*] }> <{ // CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton // CHECK-SAME: @_T04enum16DynamicSingletonOMn // CHECK-SAME: i8* null // CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*) // CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*) // -- No-payload enums have extra inhabitants in // their value witness table. // CHECK: @_T04enum10NoPayloadsOWV = internal constant [18 x i8*] [ // -- ... // -- size // CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*), // -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses // CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*), // -- stride // CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*), // -- num extra inhabitants (256 - 3 valid states) // CHECK-SAME: i8* inttoptr ([[WORD]] 253 to i8*) // -- storeExtraInhabitant // CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*) // -- getExtraInhabitantIndex // CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*) // CHECK-SAME: ] // -- Single-payload enums take unused extra inhabitants from their payload // as their own. // CHECK: @_T04enum19SinglePayloadNestedOWV = internal constant [18 x i8*] [ // -- ... // -- size // CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*), // -- flags 0x4_0000 - alignment 1, has extra inhabitants // CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*), // -- stride // CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*), // -- num extra inhabitants (253 from payload - 3 empty cases) // CHECK-SAME: i8* inttoptr ([[WORD]] 250 to i8*) // -- storeExtraInhabitant // CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*) // -- getExtraInhabitantIndex // CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*) // CHECK-SAME: ] // CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, [18 x i8*] }> <{ // CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload // CHECK-SAME: i8* null // CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*) // CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*) // CHECK: @_T04enum18MultiPayloadNestedOWV = internal constant [18 x i8*] [ // -- size // CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*), // CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*), // -- flags 0x250003 - alignment 4 // CHECK-32-SAME: i8* inttoptr ([[WORD]] {{2424835|2097155}} to i8*) // -- flags 0x200007 - alignment 8 // CHECK-64-SAME: i8* inttoptr ([[WORD]] 2097159 to i8*) // CHECK-SAME: ] enum Empty {} enum EmptySingleton { case foo } enum Singleton { case value(Builtin.Int64, Builtin.Int64) } enum SingletonRef { case value(Builtin.NativeObject) } enum DynamicSingleton { case value(T) } // CHECK-64: define{{( protected)?}} swiftcc void @singleton_switch(i64, i64) {{.*}} { // CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch(%T4enum9SingletonO* noalias nocapture dereferenceable(16)) {{.*}} { sil @singleton_switch : $(Singleton) -> () { // CHECK-64: entry: // CHECK-32: entry: entry(%u : $Singleton): // CHECK-64: br label %[[DEST:[0-9]+]] // CHECK-32: br label %[[DEST:[0-9]+]] switch_enum %u : $Singleton, case #Singleton.value!enumelt.1: dest // CHECK-64: ;