// RUN: %target-swift-frontend %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_or_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: %O4enum9Singleton = type <{ <{ i64, i64 }> }> // -- Singleton enum with heap object ref payload. // CHECK: %O4enum12SingletonRef = type <{ %swift.refcounted* }> // -- No-payload enums. The representation is just an enum tag. // CHECK: %O4enum10NoPayloads = type <{ i2 }> // CHECK: %O4enum11NoPayloads2 = type <{ i3 }> // -- 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: %O4enum17SinglePayloadNoXI = type <{ [8 x i8], [1 x i8] }> // CHECK-64: %O4enum18SinglePayloadNoXI2 = type <{ [8 x i8], [1 x i8] }> // CHECK-32: %O4enum17SinglePayloadNoXI = type <{ [4 x i8], [1 x i8] }> // CHECK-32: %O4enum18SinglePayloadNoXI2 = 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: %O4enum21SinglePayloadSpareBit = 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: %O4enum19SinglePayloadNested = 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: %O4enum25SinglePayloadNestedNested = 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: %O4enum23MultiPayloadNoSpareBits = 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: %O4enum23MultiPayloadOneSpareBit = 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: %O4enum24MultiPayloadTwoSpareBits = type <{ [8 x i8] }> // CHECK-64: %O4enum30MultiPayloadSpareBitAggregates = type <{ [16 x i8] }> // CHECK-64: %O4enum18MultiPayloadNested = type <{ [9 x i8] }> // CHECK-32: %O4enum18MultiPayloadNested = type <{ [5 x i8] }> // 32-bit object references don't have enough spare bits. // CHECK-64: %O4enum27MultiPayloadNestedSpareBits = type <{ [8 x i8] }> // -- Dynamic enums. The type layout is opaque; we dynamically bitcast to // the element type. // CHECK: %O4enum20DynamicSinglePayload = type <{}> // CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%O4enum20DynamicSinglePayload\.[0-9]+]] = type <{ [1 x i8] }> // -- Address-only multi-payload enums. We can't use spare bits. // CHECK-64: %O4enum32MultiPayloadAddressOnlySpareBits = type <{ [16 x i8], [1 x i8] }> // CHECK-32: %O4enum32MultiPayloadAddressOnlySpareBits = type <{ [8 x i8], [1 x i8] }> // CHECK: [[DYNAMIC_SINGLETON:%O4enum16DynamicSingleton.*]] = type <{}> // -- 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"O4enum16DynamicSingleton\00" // CHECK: @_TMnO4enum16DynamicSingleton = {{(protected )?}}constant <{ {{.*}} i32 }> <{ // CHECK: [25 x i8]* [[DYNAMICSINGLETON_NAME]] // -- One payload // CHECK: i32 1, // -- No empty cases // CHECK: i32 0, // -- Case names // CHECK: [[DYNAMICSINGLETON_FIELD_NAMES]] // -- Case type accessor // CHECK: @get_field_types_DynamicSingleton // -- generic parameter vector offset // CHECK: i32 3, // -- generic parameter vector length; witness table counts // CHECK: i32 1, i32 0 // CHECK: }> // CHECK: @_TMPO4enum16DynamicSingleton = {{(protected )?}}global <{ {{.*}}* }> <{ // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton // CHECK: @_TMnO4enum16DynamicSingleton // CHECK: i8* null // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwxsO4enum16DynamicSingleton to i8*) // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgO4enum16DynamicSingleton to i8*) // -- No-payload enums have extra inhabitants in // their value witness table. // CHECK: @_TWVO4enum10NoPayloads = {{(protected )?}}constant [26 x i8*] [ // -- ... // -- size // CHECK: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*), // -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses // CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*), // -- stride // CHECK: i8* inttoptr ([[WORD]] 1 to i8*), // -- num extra inhabitants (256 - 3 valid states) // CHECK: i8* inttoptr ([[WORD]] 253 to i8*) // -- storeExtraInhabitant // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwxsO4enum10NoPayloads to i8*) // -- getExtraInhabitantIndex // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgO4enum10NoPayloads to i8*) // CHECK: ] // -- Single-payload enums take unused extra inhabitants from their payload // as their own. // CHECK: @_TWVO4enum19SinglePayloadNested = {{(protected )?}}constant [26 x i8*] [ // -- ... // -- size // CHECK: i8* inttoptr ([[WORD]] 1 to i8*), // -- flags 0x4_0000 - alignment 1, has extra inhabitants // CHECK: i8* inttoptr ([[WORD]] 2359296 to i8*), // -- stride // CHECK: i8* inttoptr ([[WORD]] 1 to i8*), // -- num extra inhabitants (253 from payload - 3 empty cases) // CHECK: i8* inttoptr ([[WORD]] 250 to i8*) // -- storeExtraInhabitant // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwxsO4enum19SinglePayloadNested to i8*) // -- getExtraInhabitantIndex // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgO4enum19SinglePayloadNested to i8*) // CHECK: ] // CHECK: @_TMPO4enum20DynamicSinglePayload = {{(protected )?}}global <{ {{.*}}* }> <{ // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload // CHECK: i8* null // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwxsO4enum20DynamicSinglePayload to i8*) // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgO4enum20DynamicSinglePayload to i8*) // CHECK: @_TWVO4enum18MultiPayloadNested = {{(protected )?}}constant [26 x i8*] [ // CHECK: i8* inttoptr ([[WORD]] 9 to i8*), // CHECK: i8* inttoptr ([[WORD]] 16 to i8*) // CHECK: ] 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: define{{( protected)?}} void @singleton_switch(i64, i64) {{.*}} { sil @singleton_switch : $(Singleton) -> () { // CHECK: entry: entry(%u : $Singleton): // CHECK: br label %[[DEST:[0-9]+]] switch_enum %u : $Singleton, case #Singleton.value!enumelt.1: dest // CHECK: ;