// RUN: %target-swift-frontend %s -gnone -emit-ir | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize // REQUIRES: CPU=x86_64 import Builtin enum NoPayload { case a case b case c } enum SingletonPayload { case S(Builtin.Int64, Builtin.Int64) } enum SinglePayloadTrivial { case payload(Builtin.Int64) case a case b case c } enum SinglePayloadNontrivial { case payload(Builtin.NativeObject) case a case b case c } enum MultiPayloadTrivial { case payload1(Builtin.Int64) case payload2(Builtin.Int32, Builtin.Int32) case a case b case c } enum MultiPayloadNoEmptyCases { case payload1(Builtin.Int64) case payload2(Builtin.Int32, Builtin.Int32) } enum MultiPayloadEmptyPayload { case payload1() case payload2() case a case b case c } // No spare bits enum MultiPayloadNontrivial { case payload1(Builtin.NativeObject) case payload2(Builtin.Int64) case payload3(Builtin.Int64, Builtin.UnknownObject) case payload4(Builtin.Int64, Builtin.Int64) case a case b case c } enum MultiPayloadGeneric { case payload1(T) case payload2(T) case a case b case c } // Most significant bits of second 64-bit word of payload // are spare bits enum MultiPayloadNontrivialSpareBits { case payload1(Builtin.NativeObject) case payload2(Builtin.Int64) case payload3(Builtin.Int64, Builtin.UnknownObject) case a case b case c } // We only have 1 spare bit but 3 payload cases enum MultiPayloadSpareBitsAndExtraBits { case payload1(Builtin.Int63) case payload2(Builtin.NativeObject) case payload3(Builtin.NativeObject) } enum GenericFixedLayout { case foo(Builtin.Int64) case bar(Builtin.NativeObject) } // CHECK-LABEL: @_TWVO20enum_value_semantics20SinglePayloadTrivial = {{(protected )?}}constant [26 x i8*] [ // CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, %swift.type*)* @__swift_noop_self_return to i8*), // CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), // CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, %swift.type*)* @__swift_noop_self_return to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*), // CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memcpy_array16_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array16_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array16_8 to i8*), // CHECK: i8* inttoptr (i64 9 to i8*), // CHECK: i8* inttoptr (i64 2097159 to i8*), // CHECK: i8* inttoptr (i64 16 to i8*), // CHECK: i8* null, // CHECK: i8* null, // CHECK: i8* null, // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwugO20enum_value_semantics20SinglePayloadTrivial to i8*), // CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwupO20enum_value_semantics20SinglePayloadTrivial to i8*), // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwuiO20enum_value_semantics20SinglePayloadTrivial to i8*) // CHECK: ] // CHECK-LABEL: @_TMfO20enum_value_semantics20SinglePayloadTrivial = internal constant <{ {{.*i(32|64)}} }> <{ // CHECK: i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics20SinglePayloadTrivial, i32 0, i32 0), // CHECK: i64 2, // CHECK: {{.*}}* @_TMnO20enum_value_semantics20SinglePayloadTrivial // CHECK: i64 0 // CHECK: }> // CHECK-LABEL: @_TWVO20enum_value_semantics23SinglePayloadNontrivial = {{(protected )?}}constant [26 x i8*] [ // CHECK: i8* bitcast (void ([24 x i8]*, %swift.type*)* @_TwXXO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @_TwCPO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (i8* (i8*, %swift.type*)* @__swift_noop_self_return to i8*), // CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*), // CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwxxO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, %swift.opaque*, %swift.type*)* @_TwCpO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcpO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwcaO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy8_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy8_8 to i8*), // CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @_TwtaO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (i8* (i8*, %swift.type*)* @__swift_noop_self_return to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy8_8 to i8*), // CHECK: i8* bitcast (void (%swift.opaque*, i64, %swift.type*)* @_TwXxO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, i64, %swift.type*)* @_TwCcO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array8_8 to i8*), // CHECK: i8* bitcast (i8* (i8*, i8*, i64, %swift.type*)* @__swift_memmove_array8_8 to i8*), // CHECK: i8* inttoptr (i64 8 to i8*), // -- 0x250007 // CHECK: i8* inttoptr (i64 2424839 to i8*), // CHECK: i8* inttoptr (i64 8 to i8*), // -- on Darwin, first 4GB are unmapped: 0x7ffffffc // -- on Linux, only safe to assume first 4KB: 0x7fd // CHECK: i8* inttoptr (i64 {{2045|2147483644}} to i8*) // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwxsO20enum_value_semantics23SinglePayloadNontrivial to i8*) // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwxgO20enum_value_semantics23SinglePayloadNontrivial to i8*) // CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_TwugO20enum_value_semantics23SinglePayloadNontrivial to i8*), // CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @_TwupO20enum_value_semantics23SinglePayloadNontrivial to i8*) // CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_TwuiO20enum_value_semantics23SinglePayloadNontrivial to i8*) // CHECK: ] // CHECK-LABEL: @_TMfO20enum_value_semantics23SinglePayloadNontrivial = internal constant <{ {{.*i(32|64)}} }> <{ // CHECK: i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics23SinglePayloadNontrivial, i32 0, i32 0), // CHECK: i64 2, // CHECK: {{.*}}* @_TMnO20enum_value_semantics23SinglePayloadNontrivial // CHECK: i64 0 // CHECK: }> // CHECK-LABEL: @_TMPO20enum_value_semantics18GenericFixedLayout = {{(protected )?}}global <{{[{].*\* [}]}}> <{ // CHECK: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericFixedLayout // CHECK: i32 48, i16 1, i16 8, // CHECK: [16 x i8*] zeroinitializer, // CHECK: i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics18GenericFixedLayout, i32 0, i32 0), // CHECK: i64 2, // CHECK: {{.*}}* @_TMnO20enum_value_semantics18GenericFixedLayout // CHECK: i{{32|64}} 0 // CHECK: %swift.type* null, // CHECK: %swift.type** null // CHECK: }> sil @single_payload_nontrivial_copy_destroy : $(SinglePayloadNontrivial) -> () { bb0(%0 : $SinglePayloadNontrivial): retain_value %0 : $SinglePayloadNontrivial release_value %0 : $SinglePayloadNontrivial %v = tuple () return %v : $() } // CHECK-LABEL: define{{( protected)?}} void @single_payload_nontrivial_copy_destroy(i64) // CHECK: switch i64 %0, label [[PRESENT:%.*]] [ // CHECK-NEXT: i64 0, label [[NOT_PRESENT:%.*]] // CHECK-NEXT: i64 2, label [[NOT_PRESENT]] // CHECK-NEXT: i64 4, label [[NOT_PRESENT]] // CHECK-NEXT: ] // CHECK: [[T0:%.*]] = inttoptr i64 [[V:%.*]] to %swift.refcounted* // CHECK-NEXT: call void @rt_swift_retain(%swift.refcounted* [[T0]]) // CHECK-NEXT: br label [[NOT_PRESENT]] // CHECK: switch i64 %0, label [[PRESENT:%.*]] [ // CHECK-NEXT: i64 0, label [[NOT_PRESENT:%.*]] // CHECK-NEXT: i64 2, label [[NOT_PRESENT]] // CHECK-NEXT: i64 4, label [[NOT_PRESENT]] // CHECK-NEXT: ] // CHECK: [[T0:%.*]] = inttoptr i64 [[V:%.*]] to %swift.refcounted* // CHECK-NEXT: call void @rt_swift_release(%swift.refcounted* [[T0]]) // CHECK-NEXT: br label [[NOT_PRESENT]] // CHECK: ret void // // No payload enums // // -- NoPayload getExtraInhabitants // CHECK-LABEL: define linkonce_odr hidden i32 @_TwxgO20enum_value_semantics9NoPayload // CHECK: [[VALUE:%.*]] = load i8, i8* {{%.*}}, align 1 // CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[VALUE]] to i32 // CHECK-NEXT: [[SUB:%.*]] = sub i32 [[ZEXT]], 3 // CHECK-NEXT: [[EXTRA:%.*]] = icmp slt i32 [[SUB]], 0 // CHECK-NEXT: [[RES:%.*]] = select i1 [[EXTRA]], i32 -1, i32 [[SUB]] // CHECK-NEXT: ret i32 [[RES]] // -- NoPayload getEnumTag // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics9NoPayload // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics9NoPayload* // CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds %O20enum_value_semantics9NoPayload, %O20enum_value_semantics9NoPayload* [[SELF]], i32 0, i32 0 // CHECK-NEXT: [[TAG:%.*]] = load i2, i2* [[TAG_ADDR]], align 1 // CHECK-NEXT: [[RESULT:%.*]] = zext i2 %2 to i32 // CHECK-NEXT: ret i32 [[RESULT]] // -- NoPayload destructiveProjectEnumData // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics9NoPayload // CHECK: ret void // -- NoPayload destructiveInjectEnumTag // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics9NoPayload // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics9NoPayload* // CHECK-NEXT: [[TAG:%.*]] = trunc i32 %tag to i2 // CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds %O20enum_value_semantics9NoPayload, %O20enum_value_semantics9NoPayload* [[SELF]], i32 0, i32 0 // CHECK-NEXT: store i2 [[TAG]], i2* [[TAG_ADDR]], align 1 // CHECK-NEXT: ret void // // Singleton payload enums // // -- SingletonPayload getEnumTag // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics16SingletonPayload // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics16SingletonPayload* // CHECK-NEXT: ret i32 -1 // -- SingletonPayload destructiveProjectEnumData // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics16SingletonPayload // CHECK: ret void // -- SingletonPayload destructiveInjectEnumTag // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics16SingletonPayload // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics16SingletonPayload* // CHECK-NEXT: ret void // -- SinglePayloadTrivial getEnumTag // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics20SinglePayloadTrivial // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics20SinglePayloadTrivial* // CHECK-NEXT: [[OPAQUE:%.*]] = bitcast %O20enum_value_semantics20SinglePayloadTrivial* [[SELF]] to %swift.opaque* // CHECK-NEXT: [[TAG:%.*]] = call i32 @rt_swift_getEnumCaseSinglePayload(%swift.opaque* [[OPAQUE]], %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_TMBi64_, i32 0, i32 1), i32 3) // CHECK-NEXT: ret i32 [[TAG]] // -- SinglePayloadTrivial destructiveProjectEnumData // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics20SinglePayloadTrivial // CHECK: ret void // // Single-payload enums // // -- SinglePayloadTrivial destructiveInjectEnumTag // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics20SinglePayloadTrivial // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics20SinglePayloadTrivial* // CHECK-NEXT: [[OPAQUE:%.*]] = bitcast %O20enum_value_semantics20SinglePayloadTrivial* [[SELF]] to %swift.opaque* // CHECK-NEXT: call void @rt_swift_storeEnumTagSinglePayload(%swift.opaque* [[OPAQUE]], %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_TMBi64_, i32 0, i32 1), i32 %tag, i32 3) // CHECK-NEXT: ret void // -- SinglePayloadNontrivial destroyBuffer // CHECK: define linkonce_odr hidden void @_TwxxO20enum_value_semantics23SinglePayloadNontrivial(%swift.opaque* [[OBJ:%.*]], %swift.type* %SinglePayloadNontrivial) {{.*}} { // CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %O20enum_value_semantics23SinglePayloadNontrivial* // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics23SinglePayloadNontrivial* [[ADDR]] to i64* // CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8 // CHECK-NEXT: switch i64 %2, label %[[RELEASE_PAYLOAD:[0-9]+]] [ // CHECK: i64 0, label %[[DONE:[0-9]+]] // CHECK: i64 2, label %[[DONE]] // CHECK: i64 4, label %[[DONE]] // CHECK: ] // CHECK: ;