blob: 3dec263f3bda6033c7693bcc8b02c5d93041342e [file] [log] [blame]
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir | %FileCheck %s
sil_stage canonical
import Swift
protocol Existential {}
struct Fixed : Existential {
var x: Int
}
struct NotInlineFixed : Existential {
var x1: Double
var x2: Double
var x3: Double
var x4: Double
}
struct NonFixed<T> : Existential {
var x: T
}
// CHECK-LABEL: define {{.*}} @test_init_existential_non_fixed
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: [[CALL:%.*]] = call %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]])
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast %swift.opaque* [[CALL]] to %T25existentials_opaque_boxed8NonFixedV*
sil @test_init_existential_non_fixed : $@convention(thin) <T> (@in T) -> () {
entry(%0 : $*T):
%exist_container = alloc_stack $Existential
%value_addr = init_existential_addr %exist_container : $*Existential, $NonFixed<T>
dealloc_stack %exist_container : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden %swift.opaque* @__swift_allocate_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[METATYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METATYPE:%.*]] = load %swift.type*, %swift.type** [[METATYPE_ADDR]]
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METATYPE]]
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[FLAG_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[FLAG_WITNESS:%.*]] = load i8*, i8** [[FLAG_WITNESS_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[FLAG_WITNESS]]
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
// CHECK: [[EXISTENTIAL_BUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[EXISTENTIAL_BUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[EXISTENTIAL_BUFFER]] to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %allocateBox
//
// CHECK:done:
// CHECK: ret %swift.opaque* [[EXISTENTIAL_BUFFER_OPAQUE]]
//
// CHECK:allocateBox:
// CHECK: [[CALL:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METATYPE]])
// CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 0
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 1
// CHECK: [[ADDR_IN_BUFFER:%.*]] = bitcast [{{(24|12)}} x i8]* [[EXISTENTIAL_BUFFER]] to %swift.refcounted**
// CHECK: store %swift.refcounted* [[BOX]], %swift.refcounted** [[ADDR_IN_BUFFER]]
// CHECK: ret %swift.opaque* [[ADDR]]
// CHECK-LABEL: define {{.*}} @test_init_existential_fixed
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// The first inline buffer reference is from the emitOpaqueExistentialContainerInit call.
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %T25existentials_opaque_boxed5FixedV*
sil @test_init_existential_fixed : $@convention(thin) () -> () {
entry:
%exist_container = alloc_stack $Existential
%value_addr = init_existential_addr %exist_container : $*Existential, $Fixed
dealloc_stack %exist_container : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define {{.*}} @test_init_existential_fixed_not_inline()
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64 48|i32 40)}}, {{(i64|i32)}} 7)
// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>*
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>, <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14NotInlineFixedV*
// CHECK: [[INLINEBUFFER_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %swift.refcounted**
// CHECK: store %swift.refcounted* [[BOX]], %swift.refcounted** [[INLINEBUFFER_ADDR]]
// CHECK: ret void
sil @test_init_existential_fixed_not_inline : $@convention(thin) () -> () {
entry:
%exist_container = alloc_stack $Existential
%value_addr = init_existential_addr %exist_container : $*Existential, $NotInlineFixed
dealloc_stack %exist_container : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define {{.*}} @test_deinit_existential
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: call void @__swift_deallocate_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]])
// CHECK: ret void
sil @test_deinit_existential : $@convention(thin) () -> () {
entry:
%exist_container = alloc_stack $Existential
deinit_existential_addr %exist_container : $*Existential
dealloc_stack %exist_container : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden void @__swift_deallocate_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[META_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[META:%.*]] = load %swift.type*, %swift.type** [[META_ADDR]]
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** %3, {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[MASKED]], 0
// CHECK: br i1 [[ISINLINE]], label %done, label %deallocateBox
// CHECK: done:
// CHECK: ret void
// CHECK: deallocateBox:
// CHECK: [[BUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[REFERENCE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[BUFFER]] to %swift.refcounted**
// CHECK: [[REFERENCE:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFERENCE_ADDR]]
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[META]] to i8***
// CHECK: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
// CHECK: [[VW_ADDR2:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 9
// CHECK: [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPSIZE:%.*]] = add {{(i64|i32)}} [[ALIGNEDSTART]], [[SIZE]]
// CHECK: [[ALIGNMASK_ATLEASTPOINTER:%.*]] = or {{(i64|i32)}} [[ALIGNMASK]], {{(7|3)}}
// CHECK: [[PTR:%.*]] = bitcast %swift.refcounted* [[REFERENCE]] to i8*
// CHECK: call void @swift_slowDealloc(i8* [[PTR]], {{(i64|i32)}} [[HEAPSIZE]], {{(i64|i32)}} [[ALIGNMASK_ATLEASTPOINTER]])
// CHECK: ret void
// CHECK-LABEL: define {{.*}} @test_open_existential_addr_immutable(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: [[META_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METATYPE:%.*]] = load %swift.type*, %swift.type** [[META_ADDR]]
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[BUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[VALUE_ADDR:%.*]] = call %swift.opaque* @__swift_project_boxed_opaque_existential_1([{{(24|12)}} x i8]* [[BUFFER]], %swift.type* [[METATYPE]])
// CHECK: ret void
sil @test_open_existential_addr_immutable :$@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%1 = open_existential_addr immutable_access %0 : $*Existential to $*@opened("01234567-89ab-cdef-0123-000000000000") Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden %swift.opaque* @__swift_project_boxed_opaque_existential_1([{{(24|12)}} x i8]*, %swift.type*)
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
// CHECK: [[VALUEADDRINLINE:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %boxed
//
// CHECK: done:
// CHECK: ret %swift.opaque* [[VALUEADDRINLINE]]
//
// CHECK: boxed:
// CHECK: [[REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.refcounted**
// CHECK: [[REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFADDR]]
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPOBJ:%.*]] = bitcast %swift.refcounted* %9 to i8*
// CHECK: [[STARTOFVALUE:%.*]] = getelementptr inbounds i8, i8* [[HEAPOBJ]], {{(i64|i32)}} [[ALIGNEDSTART]]
// CHECK: [[VALUEADDRBOXED:%.*]] = bitcast i8* [[STARTOFVALUE]] to %swift.opaque*
// CHECK: ret %swift.opaque* [[VALUEADDRBOXED]]
// CHECK-LABEL: define{{( protected)?}} {{.*}} @test_open_existential_addr_mutable
// CHECK: [[META_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METATYPE:%.*]] = load %swift.type*, %swift.type** [[META_ADDR]]
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[BUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[VALUE_ADDR:%.*]] = call %swift.opaque* @__swift_mutable_project_boxed_opaque_existential_1([{{(24|12)}} x i8]* [[BUFFER]], %swift.type* [[METATYPE]])
// CHECK: ret void
sil @test_open_existential_addr_mutable :$@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%1 = open_existential_addr mutable_access %0 : $*Existential to $*@opened("01234567-89ab-cdef-0123-000000000001") Existential
%t = tuple()
return %t : $()
}
// CHECK: define{{( protected)?}} linkonce_odr hidden %swift.opaque* @__swift_mutable_project_boxed_opaque_existential_1([{{(24|12)}} x i8]*, %swift.type*)
// CHECK: [[CAST:%.*]] = bitcast %swift.type* %1 to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
// CHECK: [[VALUEADDRINLINE:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: br i1 [[ISINLINE]], label %done, label %boxed
//
// CHECK: done:
// CHECK: ret %swift.opaque* [[VALUEADDRINLINE]]
// CHECK: boxed:
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
// CHECK: [[OPAQUE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
// CHECK: [[REFANDADDR:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
// CHECK: [[REF:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 0
// CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 1
// CHECK: ret %swift.opaque* [[ADDR]]
// CHECK-LABEL: define{{( protected)?}} swiftcc void @test_destroy_existential_addr(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: call void @__swift_destroy_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* %0)
// CHECK: ret void
sil @test_destroy_existential_addr :$@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
destroy_addr %0 : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden void @__swift_destroy_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
// CHECK: [[BUFFER_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[ISNOTINLINE]], 0
// CHECK: br i1 [[ISINLINE]], label %inline, label %outline
//
// CHECK: inline:
// CHECK: [[OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[BUFFER_ADDR]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 1
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[DESTROY:%.*]] = bitcast i8* [[VW]] to void (%swift.opaque*, %swift.type*)*
// CHECK: call void [[DESTROY]](%swift.opaque* noalias [[OPAQUE]], %swift.type* [[METADATA]])
// CHECK: ret void
//
// CHECK: outline:
// CHECK: [[REFERENCE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[BUFFER_ADDR]] to %swift.refcounted**
// CHECK: [[REFERENCE:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFERENCE_ADDR]]
// CHECK: call void @swift_release(%swift.refcounted* [[REFERENCE]])
// CHECK: ret void
// CHECK-LABEL: define{{( protected)?}} swiftcc void @test_assignWithCopy_existential_addr(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: [[ALLOCA:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: call void @__swift_assign_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]], %T25existentials_opaque_boxed11ExistentialP* %0)
// CHECK: ret void
// CHECK:}
sil @test_assignWithCopy_existential_addr : $@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%s = alloc_stack $Existential
copy_addr %0 to %s : $*Existential
dealloc_stack %s : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden void @__swift_assign_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[TMPBUFFER:%.*]] = alloca [{{(24|12)}} x i8]
// CHECK: [[SELFASSIGN:%.*]] = icmp eq %T25existentials_opaque_boxed11ExistentialP* %0, %1
// CHECK: br i1 [[SELFASSIGN]], label %done, label %cont
//
// CHECK: cont:
// CHECK: [[DEST_BUFFERADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[SRC_BUFFERADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 0
// CHECK: [[DEST_TYPEADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[DEST_TYPE:%.*]] = load %swift.type*, %swift.type** [[DEST_TYPEADDR]]
// CHECK: [[SRC_TYPEADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 1
// CHECK: [[SRC_TYPE:%.*]] = load %swift.type*, %swift.type** [[SRC_TYPEADDR]]
// CHECK: [[ISSAME:%.*]] = icmp eq %swift.type* [[DEST_TYPE]], [[SRC_TYPE]]
// CHECK: br i1 [[ISSAME]], label %match, label %no-match
//
// CHECK: match:
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[FLAGS:%.*]] = ptrtoint i8* [[VW]] to {{(i64|i32)}}
// CHECK: [[MASKED:%.*]] = and {{(i64|i32)}} [[FLAGS]], 131072
// CHECK: [[ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[MASKED]], 0
// CHECK: br i1 [[ISINLINE]], label %match-inline, label %match-outline
//
// CHECK: match-inline:
// CHECK: [[DEST_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.opaque*
// CHECK: [[SRC_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 3
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[ASSIGNWITHCOPY:%.*]] = bitcast i8* [[VW]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*
// CHECK: call %swift.opaque* [[ASSIGNWITHCOPY]](%swift.opaque* [[DEST_OPAQUE]], %swift.opaque* [[SRC_OPAQUE]], %swift.type* [[DEST_TYPE]])
// CHECK: br label %done
//
// CHECK: match-outline:
// CHECK: [[DEST_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[SRC_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[DEST_REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[DEST_REFADDR]]
// CHECK: [[SRC_REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[SRC_REFADDR]]
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[SRC_REF]])
// CHECK: call void @swift_release(%swift.refcounted* [[DEST_REF]])
// CHECK: store %swift.refcounted* [[SRC_REF]], %swift.refcounted** [[DEST_REFADDR]]
// CHECK: br label %done
// CHECK: no-match:
// CHECK: store %swift.type* [[SRC_TYPE]], %swift.type** [[DEST_TYPEADDR]]
// CHECK: [[DEST_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[SRC_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 2
// CHECK: [[SRC_PTW:%.*]] = load i8**, i8*** [[SRC_PWT_ADDR]]
// CHECK: store i8** [[SRC_PTW]], i8*** [[DEST_PWT_ADDR]]
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[DEST_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[DEST_VWT:%.*]] = load i8**, i8*** [[DEST_VWT_ADDR]]
// CHECK: [[DEST_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[DEST_VWT]], i32 10
// CHECK: [[DEST_VW:%.*]] = load i8*, i8** [[DEST_VW_ADDR]]
// CHECK: [[DEST_FLAGS:%.*]] = ptrtoint i8* [[DEST_VW]] to {{(i64|i32)}}
// CHECK: [[DEST_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[DEST_FLAGS]], 131072
// CHECK: [[DEST_ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[DEST_ISNOTINLINE]], 0
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[SRC_TYPE]] to i8***
// CHECK: [[SRC_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[SRC_VWT:%.*]] = load i8**, i8*** [[SRC_VWT_ADDR]]
// CHECK: [[SRC_VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SRC_VWT]], i32 10
// CHECK: [[SRC_VW:%.*]] = load i8*, i8** [[SRC_VW_ADDR]]
// CHECK: [[SRC_FLAGS:%.*]] = ptrtoint i8* [[SRC_VW]] to {{(i64|i32)}}
// CHECK: [[SRC_ISNOTINLINE:%.*]] = and {{(i64|i32)}} [[SRC_FLAGS]], 131072
// CHECK: [[SRC_ISINLINE:%.*]] = icmp eq {{(i64|i32)}} [[SRC_ISNOTINLINE]], 0
// CHECK: br i1 [[DEST_ISINLINE]], label %dest-inline, label %dest-outline
//
// CHECK: dest-inline:
// CHECK: [[TMPBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[TMPBUFFER]] to %swift.opaque*
// CHECK: [[DESTBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 4
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[INITWITHTAKE:%.*]] = bitcast i8* [[VW]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*
// CHECK: call %swift.opaque* [[INITWITHTAKE]](%swift.opaque* noalias [[TMPBUFFER_OPAQUE]], %swift.opaque* noalias [[DESTBUFFER_OPAQUE]], %swift.type* [[DEST_TYPE]])
// CHECK: br i1 [[SRC_ISINLINE]], label %dest-inline-src-inline, label %dest-inline-src-outline
//
// CHECK: dest-inline-src-inline:
// CHECK: [[DESTBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.opaque*
// CHECK: [[SRCBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[SRC_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[INITWITHCOPY:%.*]] = bitcast i8* [[VW]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*
// CHECK: call %swift.opaque* [[INITWITHCOPY]](%swift.opaque* noalias [[DESTBUFFER_OPAQUE]], %swift.opaque* noalias [[SRCBUFFER_OPAQUE]], %swift.type* [[SRC_TYPE]])
// CHECK: br label %dest-inline-cont
//
// CHECK: dest-inline-src-outline:
// CHECK: [[DEST_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[SRC_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[SRC_REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[SRC_REFADDR]]
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[SRC_REF]])
// CHECK: store %swift.refcounted* [[SRC_REF]], %swift.refcounted** [[DEST_REFADDR]]
// CHECK: br label %dest-inline-cont
//
// CHECK: dest-inline-cont:
// CHECK: [[TMPBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[TMPBUFFER]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[DEST_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 1
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[DESTROY:%.*]] = bitcast i8* [[VW]] to void (%swift.opaque*, %swift.type*)*
// CHECK: call void [[DESTROY]](%swift.opaque* noalias [[TMPBUFFER_OPAQUE]], %swift.type* [[DEST_TYPE]])
// CHECK: br label %done
//
// CHECK: dest-outline:
// CHECK: [[DEST_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[DEST_REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[DEST_REFADDR]]
// CHECK: br i1 [[SRC_ISINLINE]], label %dest-outline-src-inline, label %dest-outline-src-outline
//
// CHECK: dest-outline-src-inline:
// CHECK: [[DESTBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.opaque*
// CHECK: [[SRCBUFFER_OPAQUE:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.opaque*
// CHECK: [[CAST:%.*]] = bitcast %swift.type* [[SRC_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[INITWITHCOPY:%.*]] = bitcast i8* [[VW]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*
// CHECK: call %swift.opaque* [[INITWITHCOPY]](%swift.opaque* noalias [[DESTBUFFER_OPAQUE]], %swift.opaque* noalias [[SRCBUFFER_OPAQUE]], %swift.type* [[SRC_TYPE]])
// CHECK: br label %dest-outline-cont
//
// CHECK: dest-outline-src-outline:
// CHECK: [[DEST_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[DEST_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[SRC_REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[SRC_BUFFERADDR]] to %swift.refcounted**
// CHECK: [[SRC_REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[SRC_REFADDR]]
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[SRC_REF]])
// CHECK: store %swift.refcounted* [[SRC_REF]], %swift.refcounted** [[DEST_REFADDR]]
// CHECK: br label %dest-outline-cont
//
// CHECK: dest-outline-cont:
// CHECK: call void @swift_release(%swift.refcounted* [[DEST_REF]])
// CHECK: br label %done
//
// CHECK: done:
// CHECK: ret void
// CHECK: define{{( protected)?}} swiftcc void @test_assignWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: [[ALLOCA:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: call void @__swift_destroy_boxed_opaque_existential_1(%T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]])
// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOb"(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[ALLOCA]])
// CHECK: ret void
sil @test_assignWithTake_existential_addr : $@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%s = alloc_stack $Existential
copy_addr [take] %0 to %s : $*Existential
dealloc_stack %s : $*Existential
%t = tuple()
return %t : $()
}
// CHECK: define linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOb"(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
// CHECK: [[LOCAL_METADATA_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 1
// CHECK: store %swift.type* [[METADATA]], %swift.type** [[LOCAL_METADATA_ADDR]]
// CHECK: [[PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[PWT:%.*]] = load i8**, i8*** [[PWT_ADDR]]
// CHECK: [[LOCAL_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 2
// CHECK: store i8** [[PWT]], i8*** [[LOCAL_PWT_ADDR]]
// CHECK: [[BUFFER_ARG_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[BUFFER_LOCAL_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 0
// CHECK: [[CAST_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST_ADDR]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 6
// CHECK: [[VW:%.*]] = load i8*, i8** [[VW_ADDR]]
// CHECK: [[INITWITHTAKEBUFFER:%.*]] = bitcast i8* [[VW]]
// CHECK: call %swift.opaque* [[INITWITHTAKEBUFFER]]({{.*}} [[BUFFER_LOCAL_ADDR]], {{.*}} [[BUFFER_ARG_ADDR]], %swift.type* [[METADATA]])
// CHECK: ret %T25existentials_opaque_boxed11ExistentialP* %1
// CHECK: define{{( protected)?}} swiftcc void @test_initWithTake_existential_addr(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: [[LOCAL:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOb"(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[LOCAL]])
// CHECK: ret void
sil @test_initWithTake_existential_addr : $@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%s = alloc_stack $Existential
copy_addr [take] %0 to [initialization] %s : $*Existential
dealloc_stack %s : $*Existential
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define{{( protected)?}} swiftcc void @test_initWithCopy_existential_addr(%T25existentials_opaque_boxed11ExistentialP*
// CHECK: [[LOCAL:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: call %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOc"(%T25existentials_opaque_boxed11ExistentialP* %0, %T25existentials_opaque_boxed11ExistentialP* [[LOCAL]])
// CHECK: ret void
// CHECK-LABEL: define linkonce_odr hidden %T25existentials_opaque_boxed11ExistentialP* @"$S25existentials_opaque_boxed11Existential_pWOc"(%T25existentials_opaque_boxed11ExistentialP*, %T25existentials_opaque_boxed11ExistentialP*)
// CHECK: [[TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 1
// CHECK: [[ARG_TYPE:%.*]] = load %swift.type*, %swift.type** [[TYPE_ADDR]]
// CHECK: [[LOCAL_TYPE_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 1
// CHECK: store %swift.type* [[ARG_TYPE]], %swift.type** [[LOCAL_TYPE_ADDR]]
// CHECK: [[PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 2
// CHECK: [[PWT:%.*]] = load i8**, i8*** [[PWT_ADDR]]
// CHECK: [[LOCAL_PWT_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 2
// CHECK: store i8** [[PWT]], i8*** [[LOCAL_PWT_ADDR]]
// CHECK: [[BUFFER_ARG_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %0, i32 0, i32 0
// CHECK: [[BUFFER_LOCAL_ADDR:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* %1, i32 0, i32 0
// CHECK: [[CAST_ADDR:%.*]] = bitcast %swift.type* [[ARG_TYPE]] to i8***
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[CAST_ADDR]], {{(i64|i32)}} -1
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
// CHECK: [[VW:%.*]] = load i8*, i8** [[VWT]]
// CHECK: [[INITWITHCOPYBUFFER:%.*]] = bitcast i8* [[VW]]
// CHECK: call %swift.opaque* [[INITWITHCOPYBUFFER]]({{.*}} noalias [[BUFFER_LOCAL_ADDR]], {{.*}} noalias [[BUFFER_ARG_ADDR]], %swift.type* [[ARG_TYPE]])
// CHECK: ret %T25existentials_opaque_boxed11ExistentialP* %1
sil @test_initWithCopy_existential_addr : $@convention(thin) (@in Existential) -> () {
bb0(%0 : $*Existential):
%s = alloc_stack $Existential
copy_addr %0 to [initialization] %s : $*Existential
dealloc_stack %s : $*Existential
%t = tuple()
return %t : $()
}
@_alignment(32)
struct FixedOveralign : Existential {
var x : Int64
}
// We have to allocate an outline buffer if the fixed size value buffer does not have the right alignment.
// CHECK-LABEL: define {{.*}} @test_init_existential_fixed_align_not_inline()
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), {{(i64|i32)}} 64, {{(i64|i32)}} 31)
// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>*
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14FixedOveralignV*
// CHECK: [[INLINEBUFFER_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %swift.refcounted**
// CHECK: store %swift.refcounted* [[BOX]], %swift.refcounted** [[INLINEBUFFER_ADDR]]
// CHECK: ret void
sil @test_init_existential_fixed_align_not_inline : $@convention(thin) () -> () {
entry:
%exist_container = alloc_stack $Existential
%value_addr = init_existential_addr %exist_container : $*Existential, $FixedOveralign
dealloc_stack %exist_container : $*Existential
%t = tuple()
return %t : $()
}