blob: b3b0c0b3d94df33e04742f71b5873b831a065d92 [file] [log] [blame]
// RUN: %target-swift-frontend %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime --check-prefix=CHECK-%target-runtime-simulator-%target-is-simulator
// REQUIRES: CPU=x86_64
import Builtin
// Enums consisting of a retainable pointer and a single empty case use nullable
// pointer value semantics.
enum NullableRefcounted {
case Ref(Builtin.NativeObject)
case None
}
// CHECK-LABEL: define internal void @"$s34enum_value_semantics_special_cases18NullableRefcountedOwxx"(%swift.opaque* noalias %object, %swift.type* %NullableRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %object to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %1 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted**
// CHECK: %2 = load %swift.refcounted*, %swift.refcounted** %1, align 8
// CHECK: call void @swift_release(%swift.refcounted* %2)
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases18NullableRefcountedOwcp"(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted**
// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK: %5 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %4)
// CHECK: store %swift.refcounted* %4, %swift.refcounted** %2, align 8
// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %6
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases18NullableRefcountedOwca"(%swift.opaque* %dest, %swift.opaque* %src, %swift.type* %NullableRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted**
// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %2, align 8
// CHECK: %5 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK: %6 = call %swift.refcounted* @swift_retain(%swift.refcounted* returned %5)
// CHECK: store %swift.refcounted* %5, %swift.refcounted** %2, align 8
// CHECK: call void @swift_release(%swift.refcounted* %4)
// CHECK: %7 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %7
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases18NullableRefcountedOwta"(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases18NullableRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.refcounted**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %1 to %swift.refcounted**
// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %2, align 8
// CHECK: %5 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK: store %swift.refcounted* %5, %swift.refcounted** %2, align 8
// CHECK: call void @swift_release(%swift.refcounted* %4)
// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases18NullableRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %6
// CHECK: }
// Enums consisting of a retainable block pointer and a single empty case use
// nullable block pointer value semantics.
enum NullableBlockRefcounted {
case Ref(@convention(block) () -> ())
case None
}
// CHECK-LABEL: define internal void @"$s34enum_value_semantics_special_cases23NullableBlockRefcountedOwxx"(%swift.opaque* noalias %object, %swift.type* %NullableBlockRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %object to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %1 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block**
// CHECK: %2 = load %objc_block*, %objc_block** %1, align 8
// CHECK: call void @_Block_release(%objc_block* %2)
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases23NullableBlockRefcountedOwcp"(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableBlockRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block**
// CHECK: %4 = load %objc_block*, %objc_block** %3, align 8
// CHECK: %5 = call %objc_block* @_Block_copy(%objc_block* %4)
// CHECK: store %objc_block* %4, %objc_block** %2, align 8
// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %6
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases23NullableBlockRefcountedOwca"(%swift.opaque* %dest, %swift.opaque* %src, %swift.type* %NullableBlockRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block**
// CHECK: %4 = load %objc_block*, %objc_block** %2, align 8
// CHECK: %5 = load %objc_block*, %objc_block** %3, align 8
// CHECK: %6 = call %objc_block* @_Block_copy(%objc_block* %5)
// CHECK: store %objc_block* %5, %objc_block** %2, align 8
// CHECK: call void @_Block_release(%objc_block* %4)
// CHECK: %7 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %7
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases23NullableBlockRefcountedOwta"(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %NullableBlockRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %dest to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %1 = bitcast %swift.opaque* %src to %T34enum_value_semantics_special_cases23NullableBlockRefcountedO*
// CHECK: %2 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %objc_block**
// CHECK: %3 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %1 to %objc_block**
// CHECK: %4 = load %objc_block*, %objc_block** %2, align 8
// CHECK: %5 = load %objc_block*, %objc_block** %3, align 8
// CHECK: store %objc_block* %5, %objc_block** %2, align 8
// CHECK: call void @_Block_release(%objc_block* %4)
// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases23NullableBlockRefcountedO* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %6
// CHECK: }
// With multiple empty cases, the nullable pointer semantics aren't used.
enum MultipleEmptyRefcounted {
case Ref(Builtin.NativeObject)
case A
case B
}
// CHECK-LABEL: define internal void @"$s34enum_value_semantics_special_cases23MultipleEmptyRefcountedOwxx"(%swift.opaque* noalias %object, %swift.type* %MultipleEmptyRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %object to %T34enum_value_semantics_special_cases23MultipleEmptyRefcountedO*
// CHECK: %1 = bitcast %T34enum_value_semantics_special_cases23MultipleEmptyRefcountedO* %0 to i64*
// CHECK: %2 = load i64, i64* %1, align 8
// CHECK: switch i64 %2, label %3 [
// CHECK: i64 0, label %5
// CHECK-native: i64 1, label %5
// CHECK-objc-simulator-false: i64 2, label %5
// CHECK-objc-simulator-true: i64 1, label %5
// CHECK: ]
// CHECK: ; <label>:3: ; preds = %entry
// CHECK: %4 = bitcast %T34enum_value_semantics_special_cases23MultipleEmptyRefcountedO* %0 to %swift.refcounted**
// CHECK: %toDestroy = load %swift.refcounted*, %swift.refcounted** %4, align 8
// CHECK: call void @swift_release(%swift.refcounted* %toDestroy)
// CHECK: br label %5
// CHECK: ; <label>:5: ; preds = %3, %entry, %entry
// CHECK: ret void
// CHECK: }
// Enums consisting of all retainable pointers and at most one empty case
// use tagged pointer value semantics—we mask off the tag bits and pass the
// pointer to the r/r functions.
class C {}
sil_vtable C {}
class D {}
sil_vtable D {}
sil @$s34enum_value_semantics_special_cases1CCfD : $@convention(method) (C) -> ()
sil @$s34enum_value_semantics_special_cases1DCfD : $@convention(method) (D) -> ()
enum AllRefcounted {
case Ref(Builtin.NativeObject)
case CRef(C)
case DRef(D)
case None
}
// CHECK-LABEL: define internal void @"$s34enum_value_semantics_special_cases13AllRefcountedOwxx"(%swift.opaque* noalias %object, %swift.type* %AllRefcounted) {{.*}} {
// CHECK: entry:
// CHECK: %0 = bitcast %swift.opaque* %object to %T34enum_value_semantics_special_cases13AllRefcountedO*
// CHECK: %1 = bitcast %T34enum_value_semantics_special_cases13AllRefcountedO* %0 to i64*
// CHECK: %2 = load i64, i64* %1, align 8
// -- 0x3fffffffffffffff
// CHECK: %3 = and i64 %2, 4611686018427387903
// CHECK: %4 = inttoptr i64 %3 to %swift.refcounted*
// CHECK: call void @swift_release(%swift.refcounted* %4)
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define internal %swift.opaque* @"$s34enum_value_semantics_special_cases13AllRefcountedOwcp"(%swift.opaque* noalias %dest, %swift.opaque* noalias %src, %swift.type* %AllRefcounted)
// -- 0x3fffffffffffffff
// CHECK: %4 = and i64 %3, 4611686018427387903
// CHECK: %5 = inttoptr i64 %4 to %swift.refcounted*
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned %5)
// CHECK: %6 = bitcast %T34enum_value_semantics_special_cases13AllRefcountedO* %0 to i64*
// -- NB: The original loaded value is stored, not the masked one.
// CHECK: store i64 %3, i64* %6, align 8
// CHECK: }
enum AllRefcountedTwoSimple {
case Ref(Builtin.NativeObject)
case CRef(C)
case DRef(D)
case None
case Nothing
}
// CHECK-LABEL: define internal void @"$s34enum_value_semantics_special_cases22AllRefcountedTwoSimpleOwxx"
// CHECK: call void @"$s34enum_value_semantics_special_cases22AllRefcountedTwoSimpleOWOy"