mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
171 lines
8.6 KiB
Plaintext
171 lines
8.6 KiB
Plaintext
// RUN: %target-swift-frontend -emit-ir %s | FileCheck %s
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
// XFAIL: linux
|
|
|
|
// CHECK: [[TYPE:%swift.type]] = type
|
|
// CHECK: [[OPAQUE:%swift.opaque]] = type opaque
|
|
// CHECK: [[C:%C4weak1C]] = type <{ [[REF:%swift.refcounted]] }>
|
|
// CHECK: [[A:%V4weak1A]] = type <{ [[WEAK:%swift.weak]] }>
|
|
// CHECK: [[WEAK]] = type
|
|
// CHECK: [[B:%V4weak1B]] = type <{ { [[WEAK]], i8** } }>
|
|
// CHECK: [[UNKNOWN:%objc_object]] = type opaque
|
|
|
|
sil_stage canonical
|
|
|
|
import Swift
|
|
|
|
class C {}
|
|
sil_vtable C {}
|
|
sil @_TFC4weak1CD : $@convention(method) (C) -> ()
|
|
|
|
protocol P : class {
|
|
func explode()
|
|
}
|
|
|
|
struct A {
|
|
weak var x : C?
|
|
}
|
|
|
|
// size 8
|
|
// flags 0x1100007 == 1114119 (non-POD, non-inline, non-bitwise-takable)
|
|
// stride 8
|
|
// CHECK: @_TWVV4weak1A = {{.*}} i8* inttoptr (i64 8 to i8*), i8* inttoptr (i64 1114119 to i8*), i8* inttoptr (i64 8 to i8*)]
|
|
|
|
sil @test_weak_load_store : $@convention(thin) (@inout A, Optional<C>) -> () {
|
|
bb0(%0 : $*A, %1 : $Optional<C>):
|
|
%2 = struct_element_addr %0 : $*A, #A.x
|
|
%3 = load_weak %2 : $*@sil_weak Optional<C>
|
|
store_weak %1 to %2 : $*@sil_weak Optional<C>
|
|
release_value %3 : $Optional<C>
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
// CHECK: define{{( protected)?}} void @test_weak_load_store([[A]]* nocapture dereferenceable({{.*}}), i64) {{.*}} {
|
|
// CHECK: [[X:%.*]] = getelementptr inbounds [[A]], [[A]]* %0, i32 0, i32 0
|
|
// CHECK-NEXT: [[T0:%.*]] = call [[C]]* bitcast ([[REF]]* ([[WEAK]]*)* @swift_weakLoadStrong to [[C]]* ([[WEAK]]*)*)([[WEAK]]* [[X]])
|
|
// CHECK-NEXT: %3 = ptrtoint %C4weak1C* %2 to i64
|
|
// CHECK-NEXT: %4 = inttoptr
|
|
// CHECK-NEXT: call void bitcast (void ([[WEAK]]*, [[REF]]*)* @swift_weakAssign to void ([[WEAK]]*, [[C]]*)*)([[WEAK]]* [[X]], [[C]]* %4)
|
|
// CHECK-NEXT: %5 = inttoptr i64 %3 to %swift.refcounted*
|
|
// CHECK-NEXT: call void @rt_swift_release([[REF]]* %5)
|
|
// CHECK-NEXT: ret void
|
|
|
|
struct B {
|
|
weak var x : P?
|
|
}
|
|
|
|
sil @test_weak_load_store_proto : $@convention(thin) (@inout B, Optional<P>) -> () {
|
|
bb0(%0 : $*B, %1 : $Optional<P>):
|
|
%2 = struct_element_addr %0 : $*B, #B.x
|
|
%3 = load_weak %2 : $*@sil_weak Optional<P>
|
|
store_weak %1 to %2 : $*@sil_weak Optional<P>
|
|
release_value %3 : $Optional<P>
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
// CHECK: define{{( protected)?}} void @test_weak_load_store_proto([[B]]* nocapture dereferenceable({{.*}}), i64, i64)
|
|
// CHECK: [[X:%.*]] = getelementptr inbounds [[B]], [[B]]* %0, i32 0, i32 0
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 0
|
|
// CHECK-NEXT: [[T1:%.*]] = call [[UNKNOWN]]* @swift_unknownWeakLoadStrong([[WEAK]]* [[T0]])
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 1
|
|
// CHECK-NEXT: [[W:%.*]] = load i8**, i8*** [[T0]], align 8
|
|
// CHECK: [[TMPOBJ:%.*]] = inttoptr {{.*}} to %objc_object*
|
|
// CHECK: [[TMPTAB:%.*]] = inttoptr {{.*}} to i8**
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 1
|
|
// CHECK-NEXT: store i8** [[TMPTAB]], i8*** [[T0]], align 8
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_unknownWeakAssign([[WEAK]]* [[T0]], [[UNKNOWN]]* [[TMPOBJ]])
|
|
// CHECK: [[RECOMPUTED_TMPOBJ:%.*]] = inttoptr {{.*}} to %objc_object*
|
|
// CHECK: call void @swift_unknownRelease(%objc_object* [[RECOMPUTED_TMPOBJ]])
|
|
|
|
sil @test_weak_alloc_stack : $@convention(thin) (Optional<P>) -> () {
|
|
bb0(%0 : $Optional<P>):
|
|
%1 = alloc_stack $@sil_weak Optional<P>
|
|
store_weak %0 to [initialization] %1 : $*@sil_weak Optional<P>
|
|
destroy_addr %1 : $*@sil_weak Optional<P>
|
|
dealloc_stack %1 : $*@sil_weak Optional<P>
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
// CHECK: define{{( protected)?}} void @test_weak_alloc_stack(i64, i64)
|
|
// CHECK: [[X:%.*]] = alloca { [[WEAK]], i8** }, align 8
|
|
// CHECK: [[TMPOBJ:%.*]] = inttoptr {{.*}} to %objc_object*
|
|
// CHECK: [[TMPTAB:%.*]] = inttoptr {{.*}} to i8**
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 1
|
|
// CHECK-NEXT: store i8** [[TMPTAB:%.*]], i8*** [[T0]], align 8
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_unknownWeakInit([[WEAK]]* [[T0]], [[UNKNOWN]]* [[TMPOBJ:%.*]])
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds { [[WEAK]], i8** }, { [[WEAK]], i8** }* [[X]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_unknownWeakDestroy([[WEAK]]* [[T0]])
|
|
// CHECK-NEXT: bitcast
|
|
// CHECK-NEXT: llvm.lifetime.end
|
|
// CHECK-NEXT: ret void
|
|
|
|
// Value witnesses for A:
|
|
|
|
// destroyBuffer
|
|
// The value is stored out of line so that the buffer is bitwise-takable.
|
|
// CHECK: define linkonce_odr hidden void @_TwXXV4weak1A([[BUFFER:\[24 x i8\]]]* [[ARG:%.*]], [[TYPE]]*
|
|
// CHECK: [[T0:%.*]] = bitcast [[BUFFER]]* [[ARG]] to [[A]]*
|
|
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[T0]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakDestroy([[WEAK]]* [[T2]])
|
|
// CHECK-NEXT: ret void
|
|
|
|
// initializeBufferWithCopyOfBuffer
|
|
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @_TwCPV4weak1A([[BUFFER]]* [[DESTBUF:%.*]], [[BUFFER]]* [[SRCBUF:%.*]], [[TYPE]]*
|
|
// CHECK: [[DEST:%.*]] = bitcast [[BUFFER]]* [[DESTBUF]] to [[A]]*
|
|
// CHECK-NEXT: [[SRC:%.*]] = bitcast [[BUFFER]]* [[SRCBUF]] to [[A]]*
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DEST]], i32 0, i32 0
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[SRC]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakCopyInit([[WEAK]]* [[T0]], [[WEAK]]* [[T1]])
|
|
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
|
|
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
|
|
|
|
// destroy
|
|
// CHECK: define linkonce_odr hidden void @_TwxxV4weak1A([[OPAQUE]]* [[ARG:%.*]], [[TYPE]]*
|
|
// CHECK: [[T0:%.*]] = bitcast [[OPAQUE]]* [[ARG]] to [[A]]*
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[T0]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakDestroy([[WEAK]]* [[T1]])
|
|
// CHECK-NEXT: ret void
|
|
|
|
// initializeBufferWithCopy
|
|
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @_TwCpV4weak1A([[BUFFER]]* [[DESTBUF:%.*]], [[OPAQUE]]* [[SRC_OPQ:%.*]], [[TYPE]]*
|
|
// CHECK: [[SRC:%.*]] = bitcast [[OPAQUE]]* [[SRC_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[DEST:%.*]] = bitcast [[BUFFER]]* [[DESTBUF]] to [[A]]*
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DEST]], i32 0, i32 0
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[SRC]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakCopyInit([[WEAK]]* [[T0]], [[WEAK]]* [[T1]])
|
|
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
|
|
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
|
|
|
|
// initializeWithCopy
|
|
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @_TwcpV4weak1A([[OPAQUE]]* [[DEST_OPQ:%.*]], [[OPAQUE]]* [[SRC_OPQ:%.*]], [[TYPE]]*
|
|
// CHECK: [[DEST:%.*]] = bitcast [[OPAQUE]]* [[DEST_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[SRC:%.*]] = bitcast [[OPAQUE]]* [[SRC_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DEST]], i32 0, i32 0
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[SRC]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakCopyInit([[WEAK]]* [[T0]], [[WEAK]]* [[T1]])
|
|
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
|
|
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
|
|
|
|
// assignWithCopy
|
|
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @_TwcaV4weak1A([[OPAQUE]]* [[DEST_OPQ:%.*]], [[OPAQUE]]* [[SRC_OPQ:%.*]], [[TYPE]]*
|
|
// CHECK: [[DEST:%.*]] = bitcast [[OPAQUE]]* [[DEST_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[SRC:%.*]] = bitcast [[OPAQUE]]* [[SRC_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[DEST_X:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DEST]], i32 0, i32 0
|
|
// CHECK-NEXT: [[SRC_X:%.*]] = getelementptr inbounds [[A]], [[A]]* [[SRC]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakCopyAssign([[WEAK]]* [[DEST_X]], [[WEAK]]* [[SRC_X]])
|
|
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
|
|
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
|
|
|
|
// assignWithTake
|
|
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @_TwtaV4weak1A([[OPAQUE]]* [[DEST_OPQ:%.*]], [[OPAQUE]]* [[SRC_OPQ:%.*]], [[TYPE]]*
|
|
// CHECK: [[DEST:%.*]] = bitcast [[OPAQUE]]* [[DEST_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[SRC:%.*]] = bitcast [[OPAQUE]]* [[SRC_OPQ]] to [[A]]*
|
|
// CHECK-NEXT: [[DEST_X:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DEST]], i32 0, i32 0
|
|
// CHECK-NEXT: [[SRC_X:%.*]] = getelementptr inbounds [[A]], [[A]]* [[SRC]], i32 0, i32 0
|
|
// CHECK-NEXT: call void @swift_weakTakeAssign([[WEAK]]* [[DEST_X]], [[WEAK]]* [[SRC_X]])
|
|
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
|
|
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
|