| // RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %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 |
| } |
| |
| sil @single_payload_nontrivial_user : $@convention(thin) (@owned SinglePayloadNontrivial) -> () |
| |
| 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<T> { |
| 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<T> { |
| case foo(Builtin.Int64) |
| case bar(Builtin.NativeObject) |
| } |
| |
| |
| // CHECK-LABEL: @_TWVO20enum_value_semantics20SinglePayloadTrivial = hidden 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 = |
| // CHECK-SAME: internal constant {{.*}} <{ |
| // CHECK-SAME: i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics20SinglePayloadTrivial, i32 0, i32 0), |
| // CHECK-SAME: i64 2, |
| // CHECK-SAME: {{.*}}* @_TMnO20enum_value_semantics20SinglePayloadTrivial |
| // CHECK-SAME: %swift.type* null |
| // CHECK-SAME: }> |
| |
| |
| // CHECK-LABEL: @_TWVO20enum_value_semantics23SinglePayloadNontrivial = hidden 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 = |
| // CHECK-SAME: internal constant {{.*}} <{ |
| // CHECK-SAME: i8** getelementptr inbounds ([26 x i8*], [26 x i8*]* @_TWVO20enum_value_semantics23SinglePayloadNontrivial, i32 0, i32 0), |
| // CHECK-SAME: i64 2, |
| // CHECK-SAME: {{.*}}* @_TMnO20enum_value_semantics23SinglePayloadNontrivial |
| // CHECK-SAME: %swift.type* null |
| // CHECK-SAME: }> |
| |
| |
| // CHECK-LABEL: @_TMPO20enum_value_semantics18GenericFixedLayout = hidden 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 : $(@owned SinglePayloadNontrivial) -> () { |
| bb0(%0 : $SinglePayloadNontrivial): |
| retain_value %0 : $SinglePayloadNontrivial |
| %1 = function_ref @single_payload_nontrivial_user : $@convention(thin) (@owned SinglePayloadNontrivial) -> () |
| apply %1(%0) : $@convention(thin) (@owned SinglePayloadNontrivial) -> () |
| release_value %0 : $SinglePayloadNontrivial |
| %v = tuple () |
| return %v : $() |
| } |
| |
| // CHECK-LABEL: define{{( protected)?}} void @single_payload_nontrivial_copy_destroy(i64) |
| // CHECK: call void @_T020enum_value_semantics23SinglePayloadNontrivialOWy |
| // CHECK-NEXT: call void @single_payload_nontrivial_user |
| // CHECK-NEXT: call void @_T020enum_value_semantics23SinglePayloadNontrivialOWe |
| // CHECK-NEXT: 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 i8, i8* [[TAG_ADDR]], align 1 |
| // CHECK-NEXT: [[RESULT:%.*]] = zext i8 %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 i8 |
| // CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds %O20enum_value_semantics9NoPayload, %O20enum_value_semantics9NoPayload* [[SELF]], i32 0, i32 0 |
| // CHECK-NEXT: store i8 [[TAG]], i8* [[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 @swift_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 @swift_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: ; <label>:[[RELEASE_PAYLOAD]] |
| // CHECK-NEXT: [[DATA_ADDR:%.*]] = bitcast %O20enum_value_semantics23SinglePayloadNontrivial* [[ADDR]] to %swift.refcounted** |
| // CHECK-NEXT: [[DATA:%.*]] = load %swift.refcounted*, %swift.refcounted** [[DATA_ADDR]], align 8 |
| // CHECK-NEXT: call void @swift_rt_swift_release(%swift.refcounted* [[DATA]]) |
| // CHECK-NEXT: br label %[[DONE]] |
| |
| // CHECK: ; <label>:[[DONE]] |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enums |
| // |
| |
| |
| // -- MultiPayloadTrivial getEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics19MultiPayloadTrivial |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics19MultiPayloadTrivial* |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics19MultiPayloadTrivial* [[SELF]] to i64* |
| |
| |
| // -- Load the low bits of the tag from the payload area |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, i64* [[PAYLOAD]], align 8 |
| |
| // -- Load the high bits of the tag from the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics19MultiPayloadTrivial, %O20enum_value_semantics19MultiPayloadTrivial* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8* |
| // CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, i8* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32 |
| |
| // -- Form tag for the payload case, or the high bits of no-payload case |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[EXTRA_TAG]], 2 |
| |
| // -- Combine them to form the tag for the no-payload case |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[NO_PAYLOAD_TAG_TMP]] to i32 |
| |
| // -- Check if we have a payload or not |
| // CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 [[PAYLOAD_TAG]], 0 |
| // CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG]], i32 [[PAYLOAD_TAG]] |
| |
| // -- Return the tag |
| // CHECK-NEXT: ret i32 [[TAG]] |
| |
| // -- MultiPayloadTrivial destructiveProjectEnumData |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics19MultiPayloadTrivial |
| // CHECK: ret void |
| |
| |
| // -- MultiPayloadTrivial destructiveInjectEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics19MultiPayloadTrivial |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics19MultiPayloadTrivial* |
| // CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 %tag, 0 |
| // CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]] |
| |
| // CHECK: ; <label>:[[HAS_NO_PAYLOAD]] |
| |
| // -- Compute the no-payload tag |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = zext i32 %tag to i64 |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics19MultiPayloadTrivial* [[SELF]] to i64* |
| |
| // -- Store the low bits of the tag in the payload area |
| // CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG]], i64* [[PAYLOAD]], align 8 |
| |
| // -- Store the high bits of the tag in the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics19MultiPayloadTrivial, %O20enum_value_semantics19MultiPayloadTrivial* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8* |
| // CHECK-NEXT: store i8 2, i8* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: br label %[[DONE:.*]] |
| |
| // CHECK: ; <label>:[[HAS_PAYLOAD]] |
| |
| // -- Store the tag in the extra tag area |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2 |
| // CHECK-NEXT: [[TAG:%.*]] = trunc i32 [[PAYLOAD_TAG]] to i8 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics19MultiPayloadTrivial, %O20enum_value_semantics19MultiPayloadTrivial* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8* |
| // CHECK-NEXT: store i8 [[TAG]], i8* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: br label %[[DONE]] |
| |
| // CHECK: ; <label>:[[DONE]] |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enums with no empty cases |
| // |
| |
| |
| // -- MultiPayloadNoEmptyCases getEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics24MultiPayloadNoEmptyCases |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics24MultiPayloadNoEmptyCases* |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics24MultiPayloadNoEmptyCases* [[SELF]] to i64* |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, i64* [[PAYLOAD]], align 8 |
| |
| // -- The payload has no spare bits and there are no empty cases, so the tag |
| // is entirely contained in the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics24MultiPayloadNoEmptyCases, %O20enum_value_semantics24MultiPayloadNoEmptyCases* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1* |
| // CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, i1* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i32 |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[EXTRA_TAG]], 2 |
| // CHECK-NEXT: ret i32 [[PAYLOAD_TAG]] |
| |
| // -- MultiPayloadNoEmptyCases destructiveProjectEnumData |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics24MultiPayloadNoEmptyCases |
| // CHECK: ret void |
| |
| |
| // -- MultiPayloadNoEmptyCases destructiveInjectEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics24MultiPayloadNoEmptyCases |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics24MultiPayloadNoEmptyCases* |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2 |
| // CHECK-NEXT: [[TAG:%.*]] = trunc i32 [[PAYLOAD_TAG]] to i1 |
| |
| // -- Store the tag in the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics24MultiPayloadNoEmptyCases, %O20enum_value_semantics24MultiPayloadNoEmptyCases* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1* |
| // CHECK-NEXT: store i1 [[TAG]], i1* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enum with empty payloads -- payload tag is not used |
| // |
| |
| |
| // -- MultiPayloadEmptyPayload getEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics24MultiPayloadEmptyPayload |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics24MultiPayloadEmptyPayload* |
| |
| // -- Load the tag from the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds %O20enum_value_semantics24MultiPayloadEmptyPayload, %O20enum_value_semantics24MultiPayloadEmptyPayload* [[SELF]], i32 0, i32 0 |
| // CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, i8* [[EXTRA_TAG_ADDR]], align 1 |
| // CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32 |
| // CHECK-NEXT: ret i32 [[EXTRA_TAG]] |
| |
| |
| // -- MultiPayloadEmptyPayload destructiveProjectEnumData |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics24MultiPayloadEmptyPayload |
| // CHECK: ret void |
| |
| |
| // -- MultiPayloadEmptyPayload destructiveInjectEnumTag |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics24MultiPayloadEmptyPayload |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics24MultiPayloadEmptyPayload* |
| |
| // -- Store the tag in the extra tag area |
| // CHECK-NEXT: [[TAG:%.*]] = trunc i32 %tag to i8 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds %O20enum_value_semantics24MultiPayloadEmptyPayload, %O20enum_value_semantics24MultiPayloadEmptyPayload* [[SELF]], i32 0, i32 0 |
| // CHECK-NEXT: store i8 [[TAG]], i8* [[EXTRA_TAG_ADDR]], align 1 |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enum with non-POD payloads |
| // |
| |
| |
| // -- MultiPayloadNontrivial destroyBuffer |
| // CHECK: define linkonce_odr hidden void @_TwxxO20enum_value_semantics22MultiPayloadNontrivial(%swift.opaque* [[OBJ:%.*]], %swift.type* %MultiPayloadNontrivial) |
| // CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %O20enum_value_semantics22MultiPayloadNontrivial* |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics22MultiPayloadNontrivial* [[ADDR]] to { i64, i64 }* |
| // CHECK-NEXT: [[PAYLOAD_0_ADDR:%.*]] = getelementptr |
| // CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, i64* [[PAYLOAD_0_ADDR]], align 8 |
| // CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr |
| // CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, i64* [[PAYLOAD_1_ADDR]], align 8 |
| // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %O20enum_value_semantics22MultiPayloadNontrivial, %O20enum_value_semantics22MultiPayloadNontrivial* %0, i32 0, i32 1 |
| // CHECK-NEXT: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8* |
| // CHECK-NEXT: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]], align 8 |
| // CHECK-NEXT: @_T020enum_value_semantics22MultiPayloadNontrivialOWy |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enum with generic layout -- spare bits are not used |
| // |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics19MultiPayloadGeneric |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics19MultiPayloadGeneric* |
| // CHECK-NEXT: [[OPAQUE:%.*]] = bitcast %O20enum_value_semantics19MultiPayloadGeneric* [[SELF]] to %swift.opaque* |
| // CHECK-NEXT: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload(%swift.opaque* [[OPAQUE]], %swift.type* %"MultiPayloadGeneric<T>") |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[TAG]], 2 |
| // CHECK-NEXT: ret i32 [[PAYLOAD_TAG]] |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics19MultiPayloadGeneric |
| // CHECK: ret void |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics19MultiPayloadGeneric |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics19MultiPayloadGeneric* |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2 |
| // CHECK: [[OPAQUE:%.*]] = bitcast %O20enum_value_semantics19MultiPayloadGeneric* [[SELF]] to %swift.opaque* |
| // CHECK-NEXT: call void @swift_storeEnumTagMultiPayload(%swift.opaque* [[OPAQUE]], %swift.type* %"MultiPayloadGeneric<T>", i32 [[PAYLOAD_TAG]]) |
| // CHECK-NEXT: ret void |
| |
| |
| // |
| // Multi-payload enum with spare bits |
| // |
| |
| |
| // -- MultiPayloadNontrivialSpareBits destroyBuffer |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwxxO20enum_value_semantics31MultiPayloadNontrivialSpareBits |
| // CHECK-SAME: (%swift.opaque* [[OBJ:%.*]], %swift.type* %MultiPayloadNontrivialSpareBits) {{.*}} { |
| // CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* [[ADDR]] to { i64, i64 }* |
| // CHECK-NEXT: [[PAYLOAD_0_ADDR:%.*]] = getelementptr |
| // CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, i64* [[PAYLOAD_0_ADDR]], align 8 |
| // CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr |
| // CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, i64* [[PAYLOAD_1_ADDR]], align 8 |
| // CHECK: call void @_T020enum_value_semantics31MultiPayloadNontrivialSpareBitsOWy |
| // CHECK-NEXT: ret void |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics31MultiPayloadNontrivialSpareBits |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* |
| |
| // -- Load the payload |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* [[SELF]] to { i64, i64 }* |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0 |
| // CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8 |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1 |
| // CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[SECOND_ADDR]], align 8 |
| |
| // -- Get the high bits of the tag from the spare bits |
| // CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = lshr i64 [[SECOND]], 62 |
| // CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = trunc i64 [[SPARE_TAG_TMP]] to i8 |
| // CHECK-NEXT: [[SPARE_TAG_TMP3:%.*]] = and i8 [[SPARE_TAG_TMP2]], 3 |
| // CHECK-NEXT: [[SPARE_TAG:%.*]] = zext i8 [[SPARE_TAG_TMP3]] to i32 |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[SPARE_TAG]], 3 |
| |
| // -- Get the low bits of the tag from the payload area |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[FIRST]] to i32 |
| |
| // -- Check if we have a payload or not |
| // CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 [[PAYLOAD_TAG]], 0 |
| |
| // -- Return the tag |
| // CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG]], i32 [[PAYLOAD_TAG]] |
| // CHECK-NEXT: ret i32 [[TAG]] |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics31MultiPayloadNontrivialSpareBits |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to { i64, i64 }* |
| |
| // -- Load the payload |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 0 |
| // CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8 |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[SECOND_ADDR]], align 8 |
| |
| // -- Strip off spare bits |
| // CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 4611686018427387903 |
| |
| // -- Store the payload |
| // CHECK-NEXT: [[SELF:%.*]] = bitcast %swift.opaque* %value to { i64, i64 }* |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 0 |
| // CHECK-NEXT: store i64 [[FIRST]], i64* [[FIRST_ADDR]], align 8 |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: store i64 [[SECOND_PROJ]], i64* [[SECOND_ADDR]], align 8 |
| // CHECK-NEXT: ret void |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics31MultiPayloadNontrivialSpareBits |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* |
| // CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 %tag, 0 |
| // CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]] |
| |
| // CHECK: ; <label>:[[HAS_NO_PAYLOAD]] |
| |
| // -- Turn the case index into a no-payload case index |
| // CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = zext i32 %tag to i64 |
| |
| // -- Store the low bits of the tag into the payload |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* [[SELF]] to { i64, i64 }* |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0 |
| // CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG]], i64* [[FIRST_ADDR]], align 8 |
| |
| // -- Store the high bits of the tag into the spare bits |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1 |
| // -- 0xc000000000000000 |
| // CHECK-NEXT: store i64 -4611686018427387904, i64* [[SECOND_ADDR]], align 8 |
| // CHECK-NEXT: br label %[[END:.*]] |
| |
| // CHECK: ; <label>:[[HAS_PAYLOAD]] |
| |
| // CHECK-NEXT: [[TAG_TMP2:%.*]] = add i32 %tag, 3 |
| |
| // -- Not really necessary |
| // CHECK-NEXT: [[TAG_TMP:%.*]] = and i32 [[TAG_TMP2]], 3 |
| |
| // -- Load the payload |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* [[SELF]] to { i64, i64 }* |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0 |
| // CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8 |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1 |
| // CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[SECOND_ADDR]], align 8 |
| |
| // -- Mask off spare bits in the payload -- 0x3fffffffffffffff |
| // CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 4611686018427387903 |
| |
| // -- Store the low bits of the tag in the spare bits of the payload |
| // CHECK-NEXT: [[TAG:%.*]] = zext i32 [[TAG_TMP]] to i64 |
| // CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = shl i64 [[TAG]], 62 |
| |
| // -- Not really necessary -- 0xc000000000000000 |
| // CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = and i64 [[SPARE_TAG_TMP2]], -4611686018427387904 |
| |
| // -- Apply the new spare bits |
| // CHECK-NEXT: [[SECOND_NEW:%.*]] = or i64 [[SECOND_PROJ]], [[SPARE_TAG_TMP]] |
| |
| // -- Store the payload back |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %O20enum_value_semantics31MultiPayloadNontrivialSpareBits* [[SELF]] to { i64, i64 }* |
| // CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0 |
| // CHECK-NEXT: store i64 [[FIRST]], i64* [[FIRST_ADDR]], align 8 |
| // CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1 |
| // CHECK-NEXT: store i64 [[SECOND_NEW]], i64* [[SECOND_ADDR]], align 8 |
| // CHECK-NEXT: br label %[[END]] |
| |
| // CHECK: ; <label>:[[END]] |
| // CHECK-NEXT: ret void |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden i32 @_TwugO20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* |
| |
| // -- Load the payload |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* [[SELF]] to i64* |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8 |
| |
| // -- Load the load bits of the tag from the extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits, %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1* |
| // CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, i1* [[EXTRA_TAG_ADDR]], align 8 |
| |
| // -- Load the high bits of the tag from the spare bits area |
| // CHECK-NEXT: [[SPARE_BITS_TMP2:%.*]] = lshr i64 [[PAYLOAD]], 63 |
| // CHECK-NEXT: [[SPARE_BITS_TMP:%.*]] = trunc i64 [[SPARE_BITS_TMP2]] to i8 |
| // CHECK-NEXT: [[SPARE_BITS:%.*]] = and i8 [[SPARE_BITS_TMP]], 1 |
| // CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i8 |
| |
| // -- Combine high bits and low bits to form tag |
| // CHECK-NEXT: [[TAG_TMP:%.*]] = shl i8 [[EXTRA_TAG]], 1 |
| // CHECK-NEXT: [[TAG:%.*]] = or i8 [[SPARE_BITS]], [[TAG_TMP]] |
| // CHECK-NEXT: [[RESULT:%.*]] = zext i8 [[TAG]] to i32 |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[RESULT]], |
| // CHECK-NEXT: ret i32 [[PAYLOAD_TAG]] |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwupO20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits |
| // CHECK: [[PAYLOAD_ADDR:%.*]] = bitcast %swift.opaque* %value to i64* |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8 |
| // -- 0x7fffffffffffffff |
| // CHECK-NEXT: [[PAYLOAD_PROJ:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807 |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %swift.opaque* %value to i64* |
| // CHECK-NEXT: store i64 [[PAYLOAD_PROJ]], i64* [[PAYLOAD_ADDR]], align 8 |
| // CHECK-NEXT: ret void |
| |
| |
| // CHECK-LABEL: define linkonce_odr hidden void @_TwuiO20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits |
| // CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* |
| // CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 3 |
| // CHECK-NEXT: [[SPARE_TAG_TMP3:%.*]] = and i32 [[PAYLOAD_TAG]], 1 |
| |
| // -- Load the payload |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* %0 to i64* |
| // CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8 |
| |
| // -- Mask off the spare bits |
| // -- 0x7fffffffffffffff |
| // CHECK-NEXT: [[PAYLOAD_PROJ:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807 |
| |
| // -- Store low bits of tag in spare bits area |
| // CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = zext i32 [[SPARE_TAG_TMP3]] to i64 |
| // CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = shl i64 [[SPARE_TAG_TMP2]], 63 |
| // -- 0x8000000000000000 |
| // CHECK-NEXT: [[SPARE_TAG:%.*]] = and i64 [[SPARE_TAG_TMP:%.*]], -9223372036854775808 |
| // CHECK-NEXT: [[PAYLOAD_NEW:%.*]] = or i64 [[PAYLOAD_PROJ]], [[SPARE_TAG]] |
| |
| // -- Store the payload |
| // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* %0 to i64* |
| // CHECK-NEXT: store i64 [[PAYLOAD_NEW]], i64* [[PAYLOAD_ADDR]], align 8 |
| |
| // -- Store high bits of tag in extra tag area |
| // CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = lshr i32 [[PAYLOAD_TAG]], 1 |
| // CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits, %O20enum_value_semantics33MultiPayloadSpareBitsAndExtraBits* [[SELF]], i32 0, i32 1 |
| // CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1* |
| // CHECK-NEXT: store i1 [[EXTRA_TAG]], i1* [[EXTRA_TAG_ADDR]], align 8 |
| // CHECK-NEXT: ret void |