Files
swift-mirror/test/IRGen/weak.sil
T
Joe Groff 53792aa64e IRGen: Make outlined enum copy/destroy lazier and better mangled.
Emit enum copy/destroy methods only when codegen demands them; they previously got emitted immediately when TypeInfo is instantiated, which led to many functions getting emitted that were never used. Also, make it so that the symbol name includes the full type of the enum instance the outlined functions operate on, so it's more obvious what they'e being used for and they can be ODRed across translation units.
2018-03-11 11:04:41 -07:00

173 lines
8.3 KiB
Plaintext

// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -O -S %s | %FileCheck %s --check-prefix=TAILCALL
// REQUIRES: CPU=x86_64
// XFAIL: linux
// CHECK-DAG: [[TYPE:%swift.type]] = type
// CHECK-DAG: [[OPAQUE:%swift.opaque]] = type opaque
// CHECK-DAG: [[C:%T4weak1CC]] = type <{ [[REF:%swift.refcounted]] }>
// CHECK-DAG: [[UNKNOWN:%objc_object]] = type opaque
// CHECK-DAG: [[A:%T4weak1AV]] = type <{ [[WEAK:%swift.weak]] }>
// CHECK-DAG: [[WEAK]] = type
// CHECK-DAG: [[B:%T4weak1BV]] = type <{ { [[WEAK]], i8** } }>
sil_stage canonical
import Swift
public class C {}
sil_vtable C {}
sil @$S4weak1CCfD : $@convention(method) (C) -> ()
protocol P : class {
func explode()
}
public struct A {
weak var x : C?
}
// size 8
// flags 0x1100007 == 1114119 (non-POD, non-inline, non-bitwise-takable)
// stride 8
// CHECK: @"$S4weak1AVWV" = {{.*}} 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)?}} swiftcc 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 %T4weak1CC* %2 to i64
// CHECK-NEXT: %4 = inttoptr
// CHECK-NEXT: call [[WEAK]]* bitcast ([[WEAK]]* ([[WEAK]]*, [[REF]]*)* @swift_weakAssign to [[WEAK]]* ([[WEAK]]*, [[C]]*)*)([[WEAK]]* returned [[X]], [[C]]* %4)
// CHECK-NEXT: %6 = inttoptr i64 %3 to %swift.refcounted*
// CHECK-NEXT: call void @swift_release([[REF]]* %6)
// 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)?}} swiftcc 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 [[WEAK]]* @swift_unknownWeakAssign([[WEAK]]* returned [[T0]], [[UNKNOWN]]* [[TMPOBJ]])
// CHECK: call void @"$S4weak1P_pSgWe"
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)?}} swiftcc 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 [[WEAK]]* @swift_unknownWeakInit([[WEAK]]* returned [[T0]], [[UNKNOWN]]* [[TMPOBJ:%.*]])
// CHECK-NEXT: call { %swift.weak, i8** }* @"$S4weak1P_pSgXwWh0_"({ %swift.weak, i8** }* [[X]])
// CHECK-NEXT: bitcast
// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: ret void
// Value witnesses for A:
// initializeBufferWithCopyOfBuffer
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @"$S4weak1AVwCP"([[BUFFER:\[24 x i8\]]]* noalias [[DESTBUF:%.*]], [[BUFFER]]* noalias [[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 [[WEAK]]* @swift_weakCopyInit([[WEAK]]* returned [[T0]], [[WEAK]]* [[T1]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
// TAILCALL: _$S4weak1AVwCP:
// TAILCALL: jmp _swift_weakCopyInit
// destroy
// CHECK: define linkonce_odr hidden void @"$S4weak1AVwxx"([[OPAQUE]]* noalias [[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
// TAILCALL: _$S4weak1AVwxx:
// TAILCALL: jmp _swift_weakDestroy
// initializeWithCopy
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @"$S4weak1AVwcp"([[OPAQUE]]* noalias [[DEST_OPQ:%.*]], [[OPAQUE]]* noalias [[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 [[WEAK]]* @swift_weakCopyInit([[WEAK]]* returned [[T0]], [[WEAK]]* [[T1]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
// TAILCALL: _$S4weak1AVwcp:
// TAILCALL: jmp _swift_weakCopyInit
// assignWithCopy
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @"$S4weak1AVwca"([[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 [[WEAK]]* @swift_weakCopyAssign([[WEAK]]* returned [[DEST_X]], [[WEAK]]* [[SRC_X]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
// TAILCALL: _$S4weak1AVwca:
// TAILCALL: jmp _swift_weakCopyAssign
// assignWithTake
// CHECK: define linkonce_odr hidden [[OPAQUE]]* @"$S4weak1AVwta"([[OPAQUE]]* noalias [[DEST_OPQ:%.*]], [[OPAQUE]]* noalias [[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 [[WEAK]]* @swift_weakTakeAssign([[WEAK]]* returned [[DEST_X]], [[WEAK]]* [[SRC_X]])
// CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[DEST]] to [[OPAQUE]]*
// CHECK-NEXT: ret [[OPAQUE]]* [[T0]]
// TAILCALL: _$S4weak1AVwtk:
// TAILCALL: jmp _swift_weakTakeInit
// TAILCALL: _$S4weak1AVwta:
// TAILCALL: jmp _swift_weakTakeAssign
// TAILCALL: _$S4weak1AVwTK:
// TAILCALL: jmp _swift_weakTakeInit