Files
swift-mirror/test/IRGen/partial_apply_coro.sil
Anthony Latsis b5aec4cc34 [test] Remove pre-rebranch nocapture matches
These were added in https://github.com/swiftlang/swift/pull/81375 (and
several other follow-up PRs because we missed a few places) and
are no longer needed.
2025-10-24 02:07:22 +01:00

2623 lines
171 KiB
Plaintext

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=OnoneSimplification -I %t -emit-ir -disable-emit-type-malloc-for-coro-frame %s -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-cpu
// REQUIRES: concurrency
import Builtin
import Swift
import resilient_struct
// Basic coroutine: a single yield and no results.
//
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { ptr, float } @yield1
// CHECK-32-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %0, float %[[ARG:.*]])
// CHECK-64-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %0, float %[[ARG:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[RET1:.*]] = insertvalue { ptr, float } poison, ptr @yield1.resume.0, 0
// CHECK-NEXT: %[[RET2:.*]] = insertvalue { ptr, float } %[[RET1]], float %[[ARG:.*]], 1
// CHECK-NEXT: ret { ptr, float } %[[RET2]]
// CHECK-NEXT: }
//
// CHECK-LABEL: define {{.*}} swiftcc void @yield1.resume.0
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK-NEXT: entryresume.0:
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//
sil [ossa] @yield1 : $@yield_once(Float) -> (@yields Float) {
bb0(%0 : $Float):
yield (%0 : $Float), resume bb1, unwind bb2
bb1:
%r = tuple ()
return %r : $()
bb2:
unwind
}
// Original caller: calls the partial apply wrapper
//
// CHECK-LABEL: define {{.*}} void @apply1
// CHECK-SAME: (float %[[ARG:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata
// CHECK-NEXT: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-NEXT: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} %TSf, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK-NEXT: store float %[[ARG]], ptr %[[PA_ARG]]
// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield1TA{{.*}}"(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]])
// CHECK-NEXT: %[[RESUME:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 0
// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1
// CHECK-arm64e: %[[CTXVAL:.*]] = ptrtoint ptr %[[CTXPTR]] to i64
// CHECK-arm64e-NEXT: %[[DISCR:.*]] call i64 @llvm.ptrauth.blend(i64 %[[CTXVAL]], i64 36124)
// CHECK-NEXT: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK-NEXT: call void @swift_release(ptr %[[PA_CTX_BOX]])
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//
// Partial apply wrapper: call the coroutine and forward yields and the resume
// function.
//
// CHECK-LABEL: define {{.*}} { ptr, float } @"$s6yield1TA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc
// CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-NEXT: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-NEXT: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} %TSf, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK-NEXT: %[[ARG:.*]] = load float, ptr %[[PA_ARG]]
// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield1(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], float %[[ARG]])
// CHECK-NEXT: %[[RESUME:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 0
// CHECK-NEXT: %[[SPILL2:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK-NEXT: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1
// CHECK: %[[RET_YIELD_PAIR0:.*]] = insertvalue { ptr, float } poison, ptr @"$s6yield1TA.resume.0", 0
// CHECK-NEXT: %[[RET_YIELD_PAIR1:.*]] = insertvalue { ptr, float } %[[RET_YIELD_PAIR0]], float %[[YIELD]], 1
// CHECK-NEXT: ret { ptr, float } %[[RET_YIELD_PAIR1]]
// CHECK-NEXT: }
//
// Partial apply resume: call the underlying coroutine for resume and unwind.
//
// CHECK-LABEL: define {{.*}} void @"$s6yield1TA.resume.0"
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-NEXT: entryresume.0:
// CHECK-NEXT: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK-NEXT: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK-NEXT: call void @free(ptr %[[FRAME]])
// CHECK-NEXT: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK-NEXT: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK-NEXT: call void @free(ptr %[[FRAME]])
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//
sil [ossa] @apply1 : $(Float) -> () {
bb0(%0 : $Float):
%coro = function_ref @yield1 : $@convention(thin) @yield_once (Float) -> (@yields Float)
%pa = partial_apply [callee_guaranteed] %coro(%0) : $@convention(thin) @yield_once (Float) -> (@yields Float)
(%float, %token) = begin_apply %pa() : $@callee_guaranteed @yield_once () -> (@yields Float)
end_apply %token as $()
destroy_value %pa : $@callee_guaranteed @yield_once () -> (@yields Float)
%r = tuple ()
return %r : $()
}
// Coroutine with a yield and a result
//
// CHECK-LABEL: define {{.*}} { ptr, float } @yield2
// CHECK-64-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %[[CTX:.*]], i64 %[[ARG0:.*]], float %[[ARG1:.*]])
// CHECK-32-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %[[CTX:.*]], i32 %[[ARG0:.*]], float %[[ARG1:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %yield2.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK-64-NEXT: store i64 %[[ARG0]], ptr %[[FRAME]]
// CHECK-32-NEXT: store i32 %[[ARG0]], ptr %[[FRAME]]
// CHECK-NEXT: %[[RET1:.*]] = insertvalue { ptr, float } poison, ptr @yield2.resume.0, 0
// CHECK-NEXT: %[[RET2:.*]] = insertvalue { ptr, float } %[[RET1]], float %[[ARG1]], 1
// CHECK-NEXT: ret { ptr, float } %[[RET2]]
// CHECK-NEXT: }
//
// CHECK-64-LABEL: define {{.*}} i64 @yield2.resume.0
// CHECK-32-LABEL: define {{.*}} i32 @yield2.resume.0
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable(16) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-NEXT: entryresume.0:
// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %yield2.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK-64-NEXT: %[[RET:.*]] = load i64, ptr %[[FRAME]]
// CHECK-64-NEXT: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], i64 undef, i64 %[[RET]]
// CHECK-64-NEXT: ret i64 %[[RET_SEL]]
// CHECK-32-NEXT: %[[RET:.*]] = load i32, ptr %[[FRAME]]
// CHECK-32-NEXT: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], i32 undef, i32 %[[RET]]
// CHECK-32-NEXT: ret i32 %[[RET_SEL]]
// CHECK-NEXT: }
//
sil [ossa] @yield2 : $@yield_once(Int, Float) -> (Int, @yields Float) {
bb0(%0 : $Int, %1 : $Float):
yield (%1 : $Float), resume bb1, unwind bb2
bb1:
return %0 : $Int
bb2:
unwind
}
// Original caller: calls the partial apply wrapper for both yields and results.
//
// CHECK-LABEL: define {{.*}} void @apply2
// CHECK-64-SAME: (i64 %[[ARG0:.*]], float %[[ARG1:.*]])
// CHECK-32-SAME: (i32 %[[ARG0:.*]], float %[[ARG1:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}
// CHECK-NEXT: %[[PA_CTX0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-NEXT: %[[PA_ARG0:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_CTX0]], i32 0, i32 0
// CHECK-64-NEXT: store i64 %[[ARG0]], ptr %[[PA_ARG0]], align 8
// CHECK-32-NEXT: store i32 %[[ARG0]], ptr %[[PA_ARG0]], align 4
// CHECK-NEXT: %[[PA_CTX1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-NEXT: %[[PA_ARG1:.*]] = getelementptr inbounds{{.*}} %TSf, ptr %[[PA_CTX1]], i32 0, i32 0
// CHECK-NEXT: store float %[[ARG1]], ptr %[[PA_ARG1]]
// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield2TA{{.*}}"(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]])
// CHECK-NEXT: %[[RESUME:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 0
// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1
// CHECK-64: %[[RESULT:.*]] = call swiftcc i64 %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK-32: %[[RESULT:.*]] = call swiftcc i32 %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK-NEXT: call void @swift_release(ptr %[[PA_CTX_BOX]])
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//
// Partial apply wrapper: receive two captured arguments, call the coroutine and
// forward yields and the resume function.
//
// CHECK-LABEL: define {{.*}} { ptr, float } @"$s6yield2TA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc
// CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-NEXT: %[[BOXPTR0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-NEXT: %[[ARG0PTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[BOXPTR0]], i32 0, i32 0
// CHECK-NEXT: %[[ARG0:.*]] = load [[ARGTYPE:i(32|64)]], ptr %[[ARG0PTR]]
// CHECK-NEXT: %[[BOXPTR1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-NEXT: %[[ARG1PTR:.*]] = getelementptr inbounds{{.*}} %TSf, ptr %[[BOXPTR1]], i32 0, i32 0
// CHECK-NEXT: %[[ARG1:.*]] = load float, ptr %[[ARG1PTR]]
// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARGTYPE]] %[[ARG0]], float %[[ARG1]])
// CHECK-NEXT: %[[RESUME:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 0
// CHECK-NEXT: %[[SPILL2:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK-NEXT: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, float } poison, ptr @"$s6yield2TA.resume.0", 0
// CHECK-NEXT: %[[RET1:.*]] = insertvalue { ptr, float } %[[RET0]], float %[[YIELD]], 1
// CHECK-NEXT: ret { ptr, float } %[[RET1]]
// CHECK-NEXT: }
//
// Partial apply resume: call the underlying coroutine for resume and return the
// result. Call the resume function for unwind as well.
//
// CHECK-32-LABEL: define {{.*}} i32 @"$s6yield2TA.resume.0"
// CHECK-64-LABEL: define {{.*}} i64 @"$s6yield2TA.resume.0"
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-NEXT: entryresume.0:
// CHECK-NEXT: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK-NEXT: %{{.*}} = call swiftcc [[ARGTYPE]] %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK-NEXT: call void @free(ptr %[[FRAME]])
// CHECK-NEXT: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK-NEXT: %[[RET:.*]] = call swiftcc [[ARGTYPE]] %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK-NEXT: call void @free(ptr %[[FRAME]])
// CHECK-NEXT: ret [[ARGTYPE]] %[[RET]]
// CHECK-NEXT: }
//
sil [ossa] @apply2 : $(Int, Float) -> () {
bb0(%0 : $Int, %1 : $Float):
%coro = function_ref @yield2 : $@convention(thin) @yield_once (Int, Float) -> (Int, @yields Float)
%pa = partial_apply [callee_guaranteed] %coro(%0, %1) : $@convention(thin) @yield_once (Int, Float) -> (Int, @yields Float)
(%float, %token) = begin_apply %pa() : $@callee_guaranteed @yield_once () -> (Int, @yields Float)
%int = end_apply %token as $(Int)
destroy_value %pa : $@callee_guaranteed @yield_once () -> (Int, @yields Float)
%r = tuple ()
return %r : $()
}
// Coroutine with a generic yield and no results
// CHECK-LABEL: define {{.*}} { ptr, ptr } @yieldgen1
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %{{.*}}, ptr noalias %[[ARG1:.*]], ptr %[[ARG2:.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: %[[SPILL_ARG2:.*]] = alloca ptr
// CHECK-NEXT: store ptr %[[ARG2]], ptr %[[SPILL_ARG2]]
// CHECK-NEXT: %[[RET1:.*]] = insertvalue { ptr, ptr } poison, ptr @yieldgen1.resume.0, 0
// CHECK-NEXT: %[[RET2:.*]] = insertvalue { ptr, ptr } %[[RET1]], ptr %[[ARG1]], 1
// CHECK-NEXT: ret { ptr, ptr } %[[RET2]]
// CHECK-NEXT: }
//
// CHECK-LABEL: define {{.*}} void @yieldgen1.resume.0
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK-NEXT: entryresume.0:
// CHECK-NEXT: %T1 = alloca ptr
// CHECK-NEXT: ret void
// CHECK-NEXT: }
//
sil @yieldgen1 : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T) {
bb0(%t : $*T):
yield (%t : $*T), resume bb1, unwind bb2
bb1:
%r = tuple ()
return %r : $()
bb2:
unwind
}
// CHECK-LABEL: define {{.*}} void @applygen1
// CHECK-SAMEL (float %[[ARG:.*]])
// CHECK-NEXT: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen1TA{{.*}}"(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr swiftself
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: call void @swift_release
// CHECK: ret void
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s9yieldgen1TA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen1(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr noalias %[[PA_CTX_BOX2:.*]], ptr @"$sSfN")
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[SPILL]], i32 0
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s9yieldgen1TA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s9yieldgen1TA.resume.0"
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-LABEL: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK-64: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-32: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 2
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK-64: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-32: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 2
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil [ossa] @applygen1 : $(Float) -> () {
bb0(%0 : $Float):
%coro = function_ref @yieldgen1 : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T)
%temp = alloc_stack $Float
store %0 to [trivial] %temp : $*Float
%pa = partial_apply [callee_guaranteed] %coro<Float>(%temp) : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T)
(%value, %token) = begin_apply %pa() : $@yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> () -> (@yields @in T) for <Float>
end_apply %token as $()
destroy_value %pa : $@yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> () -> (@yields @in T) for <Float>
dealloc_stack %temp : $*Float
%r = tuple ()
return %r : $()
}
// Coroutine with a generic yield and a generic indirect result
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @yieldgen2
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr noalias %[[ARG:.*]], ptr %[[TYPE:.*]])
// CHECK-NEXT: entry:
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 2
// CHECK: store ptr %[[TYPE]], ptr %[[SPILL2]]
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1
// CHECK: store ptr %[[ARG]], ptr %[[SPILL1]]
// CHECK: %[[SPILL0:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: store ptr %[[INDIRECT_RET]], ptr %[[SPILL0]]
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @yieldgen2.resume.0, 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
//
// CHECK-LABEL: define {{.*}} void @yieldgen2.resume.0
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 2
// CHECK: %[[TYPE:.*]] = load ptr, ptr %[[SPILL2]]
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1
// CHECK: %[[ARG:.*]] = load ptr, ptr %[[SPILL1]]
// CHECK: %[[SPILL0:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: %[[INDIRECT_RET:.*]] = load ptr, ptr %[[SPILL0]]
// CHECK: %[[VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[TYPE]], {{(i32|i64)}} -1
// CHECK: %[[VW:.*]] = load ptr, ptr %[[VW_PTR]]
// CHECK-arm64e: %[[VW_ADDR:.*]] = ptrtoint ptr %[[VW]] to i64
// CHECK-arm64e: %[[VW_AUTH:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[VW_ADDR]]
// CHECK-arm64e: %[[VW:.*]] = inttoptr i64 %[[VW_AUTH]] to ptr
// CHECK: %[[ASSIGN_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VW]], i32 3
// CHECK: %[[ASSIGN:.*]] = load ptr, ptr %[[ASSIGN_PTR]]
// CHECK: call ptr %[[ASSIGN]](ptr %[[INDIRECT_RET]], ptr %[[ARG]], ptr %[[TYPE]])
//
sil @yieldgen2 : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T) {
bb0(%outt : $*T, %t : $*T):
yield (%t : $*T), resume bb1, unwind bb2
bb1:
copy_addr %t to %outt : $*T
%r = tuple ()
return %r : $()
bb2:
unwind
}
// CHECK-LABEL: define {{.*}} void @applygen2
// CHECK-SAME: (float %[[ARG:.*]])
// CHECK-NEXT: entry:
// CHECK: %[[ARG_COPY:.*]] = alloca %TSf, align 4
// CHECK: %[[INDIRECT_RET:.*]] = alloca %TSf, align 4
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %[[ARG_COPY]])
// CHECK: %[[ARG_COPY_PTR:.*]] = getelementptr inbounds{{.*}} %TSf, ptr %[[ARG_COPY]], i32 0, i32 0
// CHECK: store float %[[ARG]], ptr %[[ARG_COPY_PTR]], align 4
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject
// CHECK: %[[PA_CTX_ARG:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSf }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[PA_CTX_ARG]], ptr align 4 %[[ARG_COPY]], i64 4, i1 false)
// CHECK-32: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[PA_CTX_ARG]], ptr align 4 %[[ARG_COPY]], i32 4, i1 false)
// CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %[[INDIRECT_RET]])
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen2TA{{.*}}"(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr %[[INDIRECT_RET]], ptr swiftself
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: call void @swift_release
// CHECK: call void @llvm.lifetime.end.p0(i64 4, ptr %[[INDIRECT_RET]])
// CHECK: call void @llvm.lifetime.end.p0(i64 4, ptr %[[ARG_COPY]])
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define internal swiftcc { ptr, ptr } @"$s9yieldgen2TA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_BOX_CTX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK-NEXT: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[SPILL]], i32 0
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[ARG:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSf }>, ptr %[[PA_BOX_CTX:.*]], i32 0, i32 1
// CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %[[SPILL2:.*]])
// CHECK-64: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[SPILL2:.*]], ptr align 8 %[[ARG]], i64 4, i1 false)
// CHECK-32: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %[[SPILL2:.*]], ptr align 4 %[[ARG]], i32 4, i1 false)
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[INDIRECT_RET]], ptr noalias %[[SPILL2]], ptr @"$sSfN")
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[SPILL]], i32 0
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s9yieldgen2TA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
// CHECK-LABEL: define {{.*}} void @"$s9yieldgen2TA.resume.0"
// CHECK-32-SAME: (ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-64-SAME: (ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0:.*]]
// CHECK: %[[CTX:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK-64: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK-32: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 2
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil [ossa] @applygen2 : $(Float) -> () {
bb0(%0 : $Float):
%coro = function_ref @yieldgen2 : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T)
%temp = alloc_stack $Float
store %0 to [trivial] %temp : $*Float
%pa = partial_apply [callee_guaranteed] %coro<Float>(%temp) : $@yield_once @convention(thin) <T where T : Copyable, T : Escapable> (@in T) -> (@yields @in T, @out T)
%out = alloc_stack $Float
(%f1, %token) = begin_apply %pa(%out) : $@yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> () -> (@yields @in T, @out T) for <Float>
%f2 = end_apply %token as $()
destroy_value %pa : $@yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> () -> (@yields @in T, @out T) for <Float>
dealloc_stack %out : $*Float
dealloc_stack %temp : $*Float
%r = tuple ()
return %r : $()
}
// Tests below are ported from partial_apply.sil and adapted to use coroutines.
class SwiftClass {}
sil_vtable SwiftClass {}
sil @$s13partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> ()
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partially_applyable_to_class(
// CHECK-SAME: ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %{{.*}}, ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @partially_applyable_to_class.resume.0, 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @partially_applyable_to_class.resume.0(
// CHECK-32-SAME: ptr noalias noundef nonnull align 4 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK-64-SAME: ptr noalias noundef nonnull align 8 dereferenceable([[BUFFER_SIZE]]) %{{.*}}, i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: ret void
// CHECK: }
//
sil @partially_applyable_to_class : $@convention(thin) @yield_once (@guaranteed SwiftClass) -> (@yields SwiftClass) {
bb0(%c : $SwiftClass):
yield (%c : $SwiftClass), resume bb1, unwind bb2
bb1:
%r = tuple ()
return %r : $()
bb2:
unwind
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_class
// CHECK-SAME: (ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s28partially_applyable_to_classTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s28partially_applyable_to_classTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s28partially_applyable_to_classTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{(4|8)}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_class : $@convention(thin) (SwiftClass) -> (@callee_guaranteed @yield_once () -> (@yields SwiftClass)) {
entry(%c : $SwiftClass):
%f = function_ref @partially_applyable_to_class : $@convention(thin) @yield_once (@guaranteed SwiftClass) -> (@yields SwiftClass)
%g = partial_apply [callee_guaranteed] %f(%c) : $@convention(thin) @yield_once (@guaranteed SwiftClass) -> (@yields SwiftClass)
return %g : $@callee_guaranteed @yield_once () -> (@yields SwiftClass)
}
sil @use_closure : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass)) -> ()
sil @use_closure_two : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass, SwiftClass)) -> ()
// CHECK-LABEL: define {{.*}} void @partial_apply_class_on_stack(
// CHECK-SAME: ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: call swiftcc void @use_closure(ptr @"$s28partially_applyable_to_classTA.{{[0-9]+}}{{.*}}", ptr %[[ARG]])
// CHECK: call void @swift_release(ptr %[[ARG]])
// CHECK: ret void
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.{{[0-9]+}}"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s28partially_applyable_to_classTA.{{[0-9]+}}.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s28partially_applyable_to_classTA.{{[0-9]+}}.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{(4|8)}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK-LABEL: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_class_on_stack : $@convention(thin) (@owned SwiftClass) -> () {
entry(%a : $SwiftClass):
%f = function_ref @partially_applyable_to_class : $@yield_once @convention(thin) (@guaranteed SwiftClass) -> (@yields SwiftClass)
%c = partial_apply [callee_guaranteed] [on_stack] %f(%a) : $@yield_once @convention(thin) (@guaranteed SwiftClass) -> (@yields SwiftClass)
%use = function_ref @use_closure : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass)) -> ()
apply %use(%c) : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass)) -> ()
dealloc_stack %c : $@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass)
strong_release %a : $SwiftClass
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partially_applyable_to_two_classes
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %[[CTX:.*]], ptr %1, ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %partially_applyable_to_two_classes.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: store ptr %[[ARG]], ptr %[[FRAME]]
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @partially_applyable_to_two_classes.resume.0, 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %1, 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @partially_applyable_to_two_classes.resume.0
// CHECK-SAME: (ptr noalias noundef nonnull align {{(4|8)}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %partially_applyable_to_two_classes.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: %[[ARG:.*]] = load ptr, ptr %[[FRAME]]
// CHECK: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], ptr undef, ptr %[[ARG]]
// CHECK: ret ptr %[[RET_SEL]]
// CHECK: }
//
sil @partially_applyable_to_two_classes : $@convention(thin) @yield_once (@guaranteed SwiftClass, @guaranteed SwiftClass) -> (@yields SwiftClass, SwiftClass) {
bb0(%c : $SwiftClass, %d : $SwiftClass):
yield (%c : $SwiftClass), resume bb1, unwind bb2
bb1:
return %d : $SwiftClass
bb2:
unwind
}
// CHECK-LABEL: define {{.*}} void @partial_apply_two_classes_on_stack
// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = alloca i8, {{(i32|i64)}} [[BUFFER_SIZE]], align 16
// CHECK: %[[BOXPTR0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr, ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR0]]
// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr, ptr }>, ptr %[[BOX]], i32 0, i32 2
// CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]]
// CHECK: call swiftcc void @use_closure_two(ptr @"$s34partially_applyable_to_two_classesTA{{.*}}", ptr %[[BOX]])
// CHECK: call void @swift_release(ptr %[[ARG0]])
// CHECK: call void @swift_release(ptr %[[ARG1]])
// CHECK: ret void
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s34partially_applyable_to_two_classesTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s34partially_applyable_to_two_classesTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[ARG0:.*]] = load ptr, ptr %[[PA_CTX0]]
// CHECK: %[[PA_CTX1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX1]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_two_classes(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[ARG0]], ptr %[[ARG1]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s34partially_applyable_to_two_classesTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s34partially_applyable_to_two_classesTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @"$s34partially_applyable_to_two_classesTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{(4|8)}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s34partially_applyable_to_two_classesTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s34partially_applyable_to_two_classesTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s34partially_applyable_to_two_classesTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret ptr %[[RET]]
// CHECK: }
//
sil @partial_apply_two_classes_on_stack : $@convention(thin) (@owned SwiftClass, @owned SwiftClass) -> () {
entry(%a : $SwiftClass, %b: $SwiftClass):
%f = function_ref @partially_applyable_to_two_classes : $@yield_once @convention(thin) (@guaranteed SwiftClass, @guaranteed SwiftClass) -> (@yields SwiftClass, SwiftClass)
%c = partial_apply [callee_guaranteed] [on_stack] %f(%a, %b) : $@yield_once @convention(thin) (@guaranteed SwiftClass, @guaranteed SwiftClass) -> (@yields SwiftClass, SwiftClass)
%use = function_ref @use_closure_two : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass, SwiftClass)) -> ()
apply %use(%c) : $@convention(thin) (@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass, SwiftClass)) -> ()
dealloc_stack %c : $@noescape @yield_once @callee_guaranteed () -> (@yields SwiftClass, SwiftClass)
strong_release %a : $SwiftClass
strong_release %b : $SwiftClass
%t = tuple()
return %t : $()
}
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @generic_captured_param
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @generic_captured_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %[[CTX:.*]], [[ARG_TYPE:(i32|i64)]] %[[ARG0:.*]], ptr %[[ARG1:.*]], ptr %[[ARG2:.*]])
// CHECK: entry:
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @generic_captured_param.resume.0, 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[ARG0]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @generic_captured_param.resume.0
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: ret void
// CHECK: }
//
sil @generic_captured_param : $@yield_once @convention(thin) <T> (Int, @inout T) -> (@yields Int) {
bb0(%i : $Int, %t : $*T):
yield (%i : $Int), resume bb1, unwind bb2
bb1:
%r = tuple ()
return %r : $()
bb2:
unwind
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_generic_capture
// CHECK-SAME: ([[ARG_TYPE]] %[[ARG0:.*]])
// CHECK: entry:
// CHECK: %[[ARG:.*]] = alloca %TSi
// CHECK: call void @llvm.lifetime.start.p0(i64 {{4|8}}, ptr %[[ARG]])
// CHECK: %[[ARGPTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[ARG]], i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG0]], ptr %[[ARGPTR]]
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]]
// CHECK: call void @llvm.lifetime.end.p0(i64 {{4|8}}, ptr %[[ARG]])
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s22generic_captured_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s22generic_captured_paramTA"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s22generic_captured_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @generic_captured_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr %[[ARG1]], ptr @"$sSiN")
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s22generic_captured_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s22generic_captured_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_generic_capture : $@convention(thin) (Int) -> (@yield_once @callee_guaranteed (Int) -> (@yields Int)) {
entry(%x : $Int):
%a = alloc_stack $Int
store %x to %a : $*Int
%f = function_ref @generic_captured_param : $@yield_once @convention(thin) <T> (Int, @inout T) -> (@yields Int)
%p = partial_apply [callee_guaranteed] %f<Int>(%a) : $@yield_once @convention(thin) <T> (Int, @inout T) -> (@yields Int)
dealloc_stack %a : $*Int
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int)
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @generic_captured_and_open_param
// CHECK: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %0, ptr noalias %1, ptr %2, ptr %T)
sil public @generic_captured_and_open_param : $@yield_once @convention(thin) <T> (@in T, @inout T) -> (@yields @in T) {
entry(%i : $*T, %io : $*T):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define{{.*}} swiftcc { ptr, ptr } @partial_apply_open_generic_capture
// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata
// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [{{4|8}} x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]]
// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [{{4|8}} x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2
// CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR2]],
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31generic_captured_and_open_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define internal swiftcc { ptr, ptr } @"$s31generic_captured_and_open_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr noalias %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [{{4|8}} x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [{{4|8}} x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK: %[[ARG2:.*]] = load ptr, ptr %[[PA_CTX2]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @generic_captured_and_open_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr noalias %[[ARG0]], ptr %[[ARG2]], ptr %[[ARG1]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s31generic_captured_and_open_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define internal swiftcc void @"$s31generic_captured_and_open_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_open_generic_capture : $@convention(thin) <T> (@inout T) -> @yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> (@in T) -> @yields @in T for <T> {
entry(%a : $*T):
%f = function_ref @generic_captured_and_open_param : $@yield_once @convention(thin) <U> (@in U, @inout U) -> (@yields @in U)
%p = partial_apply [callee_guaranteed] %f<T>(%a) : $@yield_once @convention(thin) <U> (@in U, @inout U) -> (@yields @in U)
return %p : $@yield_once @callee_guaranteed @substituted <T where T : Copyable, T : Escapable> (@in T) -> @yields @in T for <T>
}
/*****************************************************************************/
/* Swift-refcounted class captures. Optimizable by using the reference */
/* as the partial apply context. */
/*****************************************************************************/
// CHECK-LABEL: define {{.*}} { ptr, ptr } @guaranteed_captured_class_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, {{i32|i64}} %1, ptr %2)
sil public @guaranteed_captured_class_param : $@yield_once @convention(thin) (Int, @guaranteed SwiftClass) -> (@yields SwiftClass) {
entry(%i : $Int, %c : $SwiftClass):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_param
// CHECK-SAME: (ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31guaranteed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s31guaranteed_captured_class_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE:(i32|i64)]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @guaranteed_captured_class_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s31guaranteed_captured_class_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s31guaranteed_captured_class_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_guaranteed_class_param : $@convention(thin) (@owned SwiftClass) -> @yield_once @callee_guaranteed (Int) -> (@yields SwiftClass) {
bb0(%x : $SwiftClass):
%f = function_ref @guaranteed_captured_class_param : $@yield_once @convention(thin) (Int, @guaranteed SwiftClass) -> (@yields SwiftClass)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @guaranteed SwiftClass) -> (@yields SwiftClass)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields SwiftClass)
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @indirect_guaranteed_captured_class_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %0, [[ARGTYPE:i32|i64]] %1, ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE:4|8]]) %2)
sil public @indirect_guaranteed_captured_class_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClass) -> (@yields SwiftClass) {
entry(%i : $Int, %c : $*SwiftClass):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE]]) %[[ARGPTR:.*]])
// CHECK: entry:
// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s40indirect_guaranteed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s40indirect_guaranteed_captured_class_paramTA"
// CHECK: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SELFPTR:.*]] = alloca ptr
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: store ptr %[[PA_CTX_BOX]], ptr %[[SELFPTR]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_guaranteed_captured_class_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE]]) %[[SELFPTR]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s40indirect_guaranteed_captured_class_paramTA.resume.0", 0
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s40indirect_guaranteed_captured_class_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align [[ARGPTR_SIZE]] dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_indirect_guaranteed_class_param : $@convention(thin) (@in SwiftClass) -> @yield_once @callee_guaranteed (Int) -> (@yields SwiftClass) {
bb0(%x : $*SwiftClass):
%f = function_ref @indirect_guaranteed_captured_class_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClass) -> (@yields SwiftClass)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClass) -> (@yields SwiftClass)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields SwiftClass)
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @indirect_consumed_captured_class_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, [[ARGTYPE:(i32|i64)]] %1, ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE:(4|8)]]) %2)
sil public @indirect_consumed_captured_class_param : $@yield_once @convention(thin) (Int, @in SwiftClass) -> (@yields SwiftClass) {
entry(%i : $Int, %c : $*SwiftClass):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE]]) %[[ARGPTR:.*]])
// CHECK: entry:
// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s38indirect_consumed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s38indirect_consumed_captured_class_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SELFPTR:.*]] = alloca ptr
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s38indirect_consumed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %{{.*}} = call ptr @swift_retain(ptr returned %[[PA_CTX_BOX]])
// CHECK: store ptr %[[PA_CTX_BOX]], ptr %[[SELFPTR]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_consumed_captured_class_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable([[ARGPTR_SIZE]]) %[[SELFPTR]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s38indirect_consumed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s38indirect_consumed_captured_class_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s38indirect_consumed_captured_class_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s38indirect_consumed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s38indirect_consumed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s38indirect_consumed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_indirect_consumed_class_param : $@convention(thin) (@in SwiftClass) -> @yield_once @callee_guaranteed (Int) -> (@yields SwiftClass) {
bb0(%x : $*SwiftClass):
%f = function_ref @indirect_consumed_captured_class_param : $@yield_once @convention(thin) (Int, @in SwiftClass) -> (@yields SwiftClass)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @in SwiftClass) -> (@yields SwiftClass)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields SwiftClass)
}
/*****************************************************************************/
/* A non-trivial capture. Indirect applications can directly reference the */
/* field from the partial apply context. */
/*****************************************************************************/
struct SwiftClassPair { var x: SwiftClass, y: SwiftClass }
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @guaranteed_captured_class_pair_param
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @guaranteed_captured_class_pair_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, [[ARG_TYPE:(i32|i64)]] %1, ptr %2, ptr %3)
sil public @guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @guaranteed SwiftClassPair) -> (@yields Int) {
entry(%i : $Int, %c : $SwiftClassPair):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_pair_param
// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: %[[ARG0PTR:.*]] = getelementptr inbounds{{.*}} %T18partial_apply_coro14SwiftClassPairV, ptr %[[BOXPTR]], i32 0, i32 0
// CHECK: store ptr %[[ARG0]], ptr %[[ARG0PTR]]
// CHECK: %[[ARG1PTR:.*]] = getelementptr inbounds{{.*}} %T18partial_apply_coro14SwiftClassPairV, ptr %[[BOXPTR]], i32 0, i32 1
// CHECK: store ptr %[[ARG1]], ptr %[[ARG1PTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s36guaranteed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, {{i32|i64}} } @"$s36guaranteed_captured_class_pair_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s36guaranteed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_CTX_ARG1:.*]] = getelementptr inbounds{{.*}} %T18partial_apply_coro14SwiftClassPairV, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX_ARG1]]
// CHECK: %[[PA_CTX_ARG2:.*]] = getelementptr inbounds{{.*}} %T18partial_apply_coro14SwiftClassPairV, ptr %[[PA_CTX]], i32 0, i32 1
// CHECK: %[[ARG2:.*]] = load ptr, ptr %[[PA_CTX_ARG2]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @guaranteed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr %[[ARG1]], ptr %[[ARG2]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s36guaranteed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]],
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s36guaranteed_captured_class_pair_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s36guaranteed_captured_class_pair_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s36guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s36guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s36guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_guaranteed_class_pair_param : $@convention(thin) (@owned SwiftClassPair) -> @yield_once @callee_guaranteed (Int) -> (@yields Int) {
bb0(%x : $SwiftClassPair):
%f = function_ref @guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @guaranteed SwiftClassPair) -> (@yields Int)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int)
}
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @indirect_guaranteed_captured_class_pair_param
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @indirect_guaranteed_captured_class_pair_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, [[ARG_TYPE:(i32|i64)]] %1, ptr noalias captures(none) dereferenceable([[PAIR_SIZE:(8|16)]]) %2)
sil public @indirect_guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int) {
entry(%i : $Int, %c : $*SwiftClassPair):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: call void @llvm.memcpy.p0.p0.[[ARG_TYPE]](ptr align {{4|8}} %[[BOXPTR]], ptr align {{4|8}} %[[ARG]], [[ARG_TYPE]] [[PAIR_SIZE]], i1 false)
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s45indirect_guaranteed_captured_class_pair_paramTA"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %1, ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[SPILL1]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %1, ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[PA_CTX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0", 0
// CHECK: %[[RET:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_indirect_guaranteed_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> @yield_once @callee_guaranteed (Int) -> (@yields Int) {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int)
}
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @indirect_consumed_captured_class_pair_param
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @indirect_consumed_captured_class_pair_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %0, [[ARG_TYPE]] %1, ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %2)
sil public @indirect_consumed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in SwiftClassPair) -> (@yields Int) {
entry(%i : $Int, %c : $*SwiftClassPair):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: call void @llvm.memcpy.p0.p0.[[ARG_TYPE]](ptr align {{4|8}} %[[BOXPTR]], ptr align {{4|8}} %[[ARG]], [[ARG_TYPE]] [[PAIR_SIZE]], i1 false)
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s43indirect_consumed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s43indirect_consumed_captured_class_pair_paramTA"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s43indirect_consumed_captured_class_pair_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %1, ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: call void @llvm.lifetime.start.p0(i64 [[PAIR_SIZE]], ptr %[[SPILL1]])
// CHECK: %{{.*}} = call ptr @"$s18partial_apply_coro14SwiftClassPairVWOc"(ptr %[[PA_CTX]], ptr %[[SPILL1]])
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %1, ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[SPILL1]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 2
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 2
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s43indirect_consumed_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 2
// CHECK: %[[RESUME:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_indirect_consumed_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> @yield_once @callee_guaranteed (Int) -> (@yields Int) {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_consumed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @in SwiftClassPair) -> (@yields Int)
return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int)
}
// CHECK-LABEL: define {{.*}} ptr @captured_fixed_and_dependent_params
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, ptr %1, ptr noalias %2, [[ARG_TYPE:(i32|i64)]] %3, ptr %A)
sil public @captured_fixed_and_dependent_params : $@yield_once @convention(thin) <A> (@guaranteed SwiftClass, @in_guaranteed A, Int) -> () {
entry(%c : $SwiftClass, %a : $*A, %i : $Int):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define{{.*}} swiftcc { ptr, ptr } @partial_apply_indirect_non_fixed_layout
// CHECK-SAME: (ptr %[[CTX:.*]], ptr noalias %[[ARG0:.*]], [[ARG_TYPE]] %[[ARG1:.*]], ptr %[[TY:.*]])
// CHECK: entry:
// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], {{i32|i64}} -1
// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]]
// CHECK-arm64e: %[[VWTABLEADDR:.*]] = ptrtoint ptr %[[VWTABLE]] to i64
// CHECK-arm64e: %[[VWTABLEAUTH:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[VWTABLEADDR]], i32 2
// CHECK-arm64e: %[[VWTABLE:.*]] = inttoptr i64 %[[VWTABLEAUTH]] to ptr
// CHECK: %[[WITNESS:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 10
// CHECK: %[[FLAGS:.*]] = load i32, ptr %[[WITNESS]]
// do not check computation of align; may be target dependent
// CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8
// do not check computation of size; may be target dependent
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata{{.*}}
// CHECK-32: %[[BOXPTR0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK-64: %[[BOXPTR0:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[TY]], ptr %[[BOXPTR0]]
// CHECK-32: %[[BOXPTR1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2
// CHECK-64: %[[BOXPTR1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2
// CHECK: store ptr %[[CTX]], ptr %[[BOXPTR1]]
// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds i8, ptr %[[BOX]]
// CHECK: %[[INITPTR:.*]] = getelementptr inbounds ptr, ptr %[[VWTABLE]], i32 4
// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INITPTR]]
// CHECK: %{{.*}} = call ptr %[[INIT]](ptr noalias %[[BOXPTR2]], ptr noalias %[[ARG0]], ptr %[[TY]])
// CHECK: %[[BOXPTR3:.*]] = getelementptr inbounds i8, ptr %[[BOX]], {{i32|i64}} %{{.*}}
// CHECK: %[[BOXPTR3VAL:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[BOXPTR3]], i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG1]], ptr %[[BOXPTR3VAL]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s35captured_fixed_and_dependent_paramsTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define internal swiftcc ptr @"$s35captured_fixed_and_dependent_paramsTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[TY:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: store ptr %[[TY]], ptr %[[TY]]
// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], {{i32|i64}} -1
// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]]
// CHECK-arm64e: %[[VWTABLEADDR:.*]] = ptrtoint ptr %[[VWTABLE]] to i64
// CHECK-arm64e: %[[VWTABLEAUTH:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[VWTABLEADDR]], i32 2
// CHECK-arm64e: %[[VWTABLE:.*]] = inttoptr i64 %[[VWTABLEAUTH]] to ptr
// CHECK: %[[WITNESS:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 10
// CHECK: %[[FLAGS:.*]] = load i32, ptr %[[WITNESS]]
// do not check computation of align; may be target dependent
// CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8
// do not check computation of size; may be target dependent
// CHECK-32: %[[PA_CTX2:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-64: %[[PA_CTX2:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK: %[[ARG0:.*]] = load ptr, ptr %[[PA_CTX2]]
// CHECK: %[[ARG1:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], {{i32|i64}} %{{.*}}
// CHECK: %[[ARG2PTR0:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], {{i32|i64}} %{{.*}}
// CHECK: %[[ARG2PTR1:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[ARG2PTR0]], i32 0, i32 0
// CHECK: %[[ARG2:.*]] = load [[ARG_TYPE]], ptr %[[ARG2PTR1]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[RESUME:.*]] = call swiftcc ptr @captured_fixed_and_dependent_params(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr %[[ARG0]], ptr noalias %[[ARG1]], [[ARG_TYPE]] %[[ARG2]], ptr %T)
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: ret ptr @"$s35captured_fixed_and_dependent_paramsTA.resume.0"
// CHECK: }
//
// CHECK-LABEL: define internal swiftcc void @"$s35captured_fixed_and_dependent_paramsTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_indirect_non_fixed_layout : $@convention(thin) <T> (@owned SwiftClass, @in T, Int) -> @yield_once @callee_guaranteed () -> () {
bb0(%a : $SwiftClass, %b : $*T, %c : $Int):
%f = function_ref @captured_fixed_and_dependent_params : $@yield_once @convention(thin) <B> (@guaranteed SwiftClass, @in_guaranteed B, Int) -> ()
%p = partial_apply [callee_guaranteed] %f<T>(%a, %b, %c) : $@yield_once @convention(thin) <C> (@guaranteed SwiftClass, @in_guaranteed C, Int) -> ()
return %p : $@yield_once @callee_guaranteed () -> ()
}
// CHECK-LABEL: @partial_apply_with_out_param
// CHECK-SAME: (ptr noalias %[[ARG:.*]], ptr %[[ARGTY:.*]])
// CHECK: entry:
// CHECK: %[[ARGTY_VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[ARGTY]], {{i32|i64}} -1
// CHECK: %[[ARGTY_VW:.*]] = load ptr, ptr %[[ARGTY_VW_PTR]]
// CHECK-arm64e: %[[VWTABLEADDR:.*]] = ptrtoint ptr %[[ARGTY_VW]] to i64
// CHECK-arm64e: %[[VWTABLEAUTH:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[VWTABLEADDR]], i32 2
// CHECK-arm64e: %[[ARGTY_VW:.*]] = inttoptr i64 %[[VWTABLEAUTH]] to ptr
// CHECK: %[[ARGTY_FLAGS_PTR:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[ARGTY_VW]], i32 0, i32 10
// CHECK: %[[ARGTY_FLAGS:.*]] = load i32, ptr %[[ARGTY_FLAGS_PTR]]
// do not check computation of align; may be target dependent
// CHECK: %[[ARGTY_SIZE_PTR:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[ARGTY_VW]], i32 0, i32 8
// do not check computation of size; may be target dependent
// CHECK: %[[PA_BOX_ALLOC:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @{{.*}}
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8] }>, ptr %[[PA_BOX_ALLOC]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_BOX_ALLOC]], i32 0, i32 1
// CHECK: store ptr %[[ARGTY]], ptr %[[PA_CTX]]
// CHECK: %[[PA_CTX_ARG:.*]] = getelementptr inbounds i8, ptr %[[PA_BOX_ALLOC]],
// CHECK: %[[INIT_PTR:.*]] = getelementptr inbounds ptr, ptr %[[ARGTY_VW]], i32 4
// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INIT_PTR]]
// CHECK: call ptr %[[INIT]](ptr noalias %[[PA_CTX_ARG]], ptr noalias %[[ARG]], ptr %[[ARGTY]])
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s28captured_dependent_out_paramTA{{.*}}", ptr undef }, ptr %[[PA_BOX_ALLOC]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
//
// CHECK-LABEL: define {{.*}} @"$s28captured_dependent_out_paramTA"
// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28captured_dependent_out_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[TY:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], {{i32|i64}} -1
// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]]
// CHECK-arm64e: %[[VWTABLEADDR:.*]] = ptrtoint ptr %[[VWTABLE]] to i64
// CHECK-arm64e: %[[VWTABLEAUTH:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[VWTABLEADDR]], i32 2
// CHECK-arm64e: %[[VWTABLE:.*]] = inttoptr i64 %[[VWTABLEAUTH]] to ptr
// CHECK: %[[WITNESS:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 10
// CHECK: %[[FLAGS:.*]] = load i32, ptr %[[WITNESS]]
// do not check computation of align; may be target dependent
// CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8
// do not check computation of size; may be target dependent
// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]]
// CHECK: %[[ARG_COPY:.*]] = call ptr @malloc
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr %[[ARG_COPY]])
// CHECK: %[[INIT_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VWTABLE]], i32 2
// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INIT_PTR]]
// CHECK: call ptr %[[INIT]](ptr noalias %[[ARG_COPY]], ptr noalias %[[PA_CTX2]], ptr %[[TY]])
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @captured_dependent_out_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr %[[INDIRECT_RET]], ptr noalias %[[ARG_COPY]], ptr %[[TY]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s28captured_dependent_out_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s28captured_dependent_out_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1:.*]]
sil public @captured_dependent_out_param : $@yield_once @convention(thin) <A> (@in A) -> (@out A, @yields @in A) {
entry(%o : $*A, %i : $*A):
%0 = builtin "int_trap"() : $Never
unreachable
}
sil @partial_apply_with_out_param : $@convention(thin) <T> (@in T) -> @yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> (@out T, @yields @in T) for <T> {
bb0(%x : $*T):
%f = function_ref @captured_dependent_out_param : $@yield_once @convention(thin) <B> (@in B) -> (@out B, @yields @in B)
%p = partial_apply [callee_guaranteed] %f<T>(%x) : $@yield_once @convention(thin) <C> (@in C) -> (@out C, @yields @in C)
return %p : $@yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> (@out T, @yields @in T) for <T>
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_dynamic_with_out_param
// CHECK-SAME: (i32 %[[ARG1:.*]], ptr %[[ARG_FUNC:.*]], ptr %[[ARG_FUNC_SELF:.*]], ptr %[[TY:.*]])
// CHECK: entry:
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata
// CHECK-32: %[[PA_ARG1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_ARG1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG1_INT:.*]] = getelementptr inbounds{{.*}} %Ts5Int32V, ptr %[[PA_ARG1]], i32 0, i32 0
// CHECK: store i32 %[[ARG1]], ptr %[[PA_ARG1_INT]]
// CHECK-32: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-64: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3
// CHECK: store ptr %[[ARG_FUNC_SELF]], ptr %[[PA_ARG_FUNC_SELF]]
// CHECK-32: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3
// CHECK-64: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 4
// CHECK-arm64e: %[[ARG_FUNC_ADDR:.*]] = ptrtoint ptr %[[ARG_FUNC]] to i64
// CHECK-arm64e: %[[ARG_FUNC_AUTH:.*]] = call i64 @llvm.ptrauth.resign(i64 %[[ARG_FUNC_ADDR]]
// CHECK-arm64e: %[[ARG_FUNC:.*]] = inttoptr i64 %[[ARG_FUNC_AUTH]] to ptr
// CHECK: store ptr %[[ARG_FUNC]], ptr %[[PA_ARG_FUNC]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$sTA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$sTA"
// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$sTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-32: %[[PA_ARG1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_ARG1:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG1_INT:.*]] = getelementptr inbounds{{.*}} %Ts5Int32V, ptr %[[PA_ARG1]], i32 0, i32 0
// CHECK: %[[ARG1:.*]] = load i32, ptr %[[PA_ARG1_INT]]
// CHECK-32: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-64: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3
// CHECK: %[[ARG_FUNC_SELF:.*]] = load ptr, ptr %[[PA_ARG_FUNC_SELF]]
// CHECK-32: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3
// CHECK-64: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 4
// CHECK: %[[ARG_FUNC:.*]] = load ptr, ptr %[[PA_ARG_FUNC]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } %[[ARG_FUNC]](ptr noalias {{.*}} %[[FRAMEPTR]], ptr %[[INDIRECT_RET]], i32 %[[ARG1]], ptr swiftself %[[ARG_FUNC_SELF]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$sTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$sTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
sil @partial_apply_dynamic_with_out_param : $@convention(thin) <T> (Int32, @owned @yield_once @callee_guaranteed (Int32) -> (@out T, @yields @in T)) -> @yield_once @callee_guaranteed () -> (@out T, @yields @in T) {
bb0(%x : $Int32, %f : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields @in T)):
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields @in T)
return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields @in T)
}
// Verify that the partial apply function is unique (even if it is not uniquely mangled)
//
// CHECK: define {{.*}} { ptr, ptr } @partial_apply_dynamic_with_out_param_another
// CHECK: entry:
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$sTA.{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
sil @partial_apply_dynamic_with_out_param_another : $@convention(thin) <T> (Int64, @owned @yield_once @callee_guaranteed (Int64) -> (@out T, @yields @in T)) -> @yield_once @callee_guaranteed () -> (@out T, @yields @in T) {
bb0(%x : $Int64, %f : $@yield_once @callee_guaranteed (Int64) -> (@out T, @yields @in T)):
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @callee_guaranteed (Int64) -> (@out T, @yields @in T)
return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields @in T)
}
class Base {
}
sil_vtable Base {}
class Sub : Base {
}
sil_vtable Sub {}
sil public_external @receive_closure : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> ()
sil public_external @receive_closure2 : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> ()
// CHECK-LABEL: define {{.*}} { ptr, ptr } @parametric_casting_closure
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %[[CTX:.*]], ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
// CHECK: entry:
// CHECK: %[[ARG0CAST:.*]] = call ptr @swift_dynamicCastClassUnconditional(ptr %[[ARG0]], ptr %[[ARG1]], ptr null, i32 0, i32 0)
// CHECK: %[[SPILL:.*]] = getelementptr inbounds %parametric_casting_closure.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: store ptr %[[ARG0CAST]], ptr %[[SPILL]]
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @parametric_casting_closure.resume.0, 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[ARG0CAST]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @parametric_casting_closure.resume.0
// CHECK: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %parametric_casting_closure.Frame, ptr %[[CTX]], i32 0, i32 0
// CHECK: %[[RET:.*]] = load ptr, ptr %[[FRAME]]
// CHECK: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], ptr undef, ptr %[[RET]]
// CHECK: ret ptr %[[RET_SEL]]
// CHECK: }
//
sil @parametric_casting_closure : $@yield_once @convention(thin) <C where C : Base> (@guaranteed Base) -> (@owned C, @yields C) {
bb0(%0 : $Base):
%1 = unconditional_checked_cast %0 : $Base to C
yield (%1 : $C), resume bb1, unwind bb2
bb1:
return %1 : $C
bb2:
unwind
}
// CHECK-LABEL: define{{.*}} swiftcc void @test_partial_apply
// CHECK-SAME: (ptr %[[ARG0:.*]])
// CHECK: entry:
// CHECK: %[[CTX0:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[CTX1:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[CTX0PTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX0]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTX0PTR]])
// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"
// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0
// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}{{.*}}", ptr %[[ARG0]], ptr %[[MD]])
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0PTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTX0PTR]])
// CHECK: %[[CTX1PTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX1]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTX1PTR]])
// CHECK: %[[RESUME1:.*]] = call swiftcc ptr @receive_closure2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1PTR]], ptr @"$s26parametric_casting_closureTA{{.*}}", ptr null, ptr %[[MD]])
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1PTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTX1PTR]])
// CHECK: ret void
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr %1, ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"
// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %1, ptr %[[MD]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s26parametric_casting_closureTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @"$s26parametric_casting_closureTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret ptr %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.{{[0-9]+}}"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"
// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]], ptr %[[MD]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]],
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret ptr %[[RET]]
// CHECK: }
//
sil @test_partial_apply : $@convention(thin) (@owned Base) -> () {
bb0(%0 : $Base):
%1 = function_ref @parametric_casting_closure : $@yield_once @convention(thin) <C where C : Base> (@guaranteed Base) -> (@owned C, @yields C)
%6 = partial_apply [callee_guaranteed] %1<Sub>() : $@yield_once @convention(thin) <C where C : Base> (@guaranteed Base) -> (@owned C, @yields C)
%2 = partial_apply [callee_guaranteed] %1<Sub>(%0) : $@yield_once @convention(thin) <C where C : Base> (@guaranteed Base) -> (@owned C, @yields C)
%3 = function_ref @receive_closure : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> ()
%2c = convert_function %2: $@yield_once @callee_guaranteed @substituted <C where C : Base> () -> (@owned C, @yields C) for <Sub> to $@yield_once @callee_guaranteed () -> (@owned Sub, @yields Sub)
%t1 = begin_apply %3<Sub>(%2c) : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> ()
end_apply %t1 as $()
%5 = function_ref @receive_closure2 : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> ()
%6c = convert_function %6: $@yield_once @callee_guaranteed @substituted <C where C : Base> (@guaranteed Base) -> (@owned C, @yields C) for <Sub> to $@yield_once @callee_guaranteed (@guaranteed Base) -> (@owned Sub, @yields Sub)
%t2 = begin_apply %5<Sub>(%6c) : $@yield_once @convention(thin) <C where C : Base> (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> ()
end_apply %t2 as $()
%7 = tuple ()
return %7 : $()
}
protocol P0 {}
protocol P1 { associatedtype X : P0 }
protocol P2 { associatedtype Y : P1 }
// CHECK-LABEL: define {{.*}} void @partial_apply_complex_generic_function
// CHECK-SAME: ([[ARG_TYPE:(i32|i64)]] %[[ARG:.*]], ptr %[[TY1:.*]], ptr %[[TY2:.*]], ptr %[[TY3:.*]])
// CHECK: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}}
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [12 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: store ptr %[[TY1]], ptr %[[PA_CTX]]
// CHECK: %[[PA_CTX1:.*]] = getelementptr inbounds ptr, ptr %[[PA_CTX]], i32 1
// CHECK: store ptr %[[TY2]], ptr %[[PA_CTX1]]
// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds ptr, ptr %[[PA_CTX]], i32 2
// CHECK: store ptr %[[TY3]], ptr %[[PA_CTX2]]
// CHECK-32: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [12 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-64: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK: %[[PA_ARG_PTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_ARG]], i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG]], ptr %[[PA_ARG_PTR]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s24complex_generic_functionTA{{.*}}"(ptr noalias {{.*}} %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias {{.*}} %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s24complex_generic_functionTA"
// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s24complex_generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [12 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[TY1:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[TY2_PTR:.*]] = getelementptr inbounds ptr, ptr %[[PA_CTX]], i32 1
// CHECK: %[[TY2:.*]] = load ptr, ptr %[[TY2_PTR]]
// CHECK: %[[TY3_PTR:.*]] = getelementptr inbounds ptr, ptr %[[PA_CTX]], i32 2
// CHECK: %[[TY3:.*]] = load ptr, ptr %[[TY3_PTR]]
// CHECK-32: %[[PA_ARG_PTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [12 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK-64: %[[PA_ARG_PTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2
// CHECK: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_ARG_PTR]], i32 0, i32 0
// CHECK: %[[ARG:.*]] = load [[ARG_TYPE]], ptr %[[PA_ARG]]
// CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]])
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @complex_generic_function(ptr noalias {{.*}} %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG]], ptr %[[TY1]], ptr %[[TY2]], ptr %[[TY3]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s24complex_generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s24complex_generic_functionTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
sil hidden_external @complex_generic_function : $@yield_once @convention(thin) <T where T : P2, T.Y : P2> (Int) -> (@yields @in T)
sil @partial_apply_complex_generic_function : $@convention(thin) <T where T : P2, T.Y : P2> (Int) -> () {
bb0(%0 : $Int):
%fn = function_ref @complex_generic_function : $@yield_once @convention(thin) <T where T : P2, T.Y : P2> (Int) -> (@yields @in T)
%pa = partial_apply %fn <T>(%0) : $@yield_once @convention(thin) <T where T : P2, T.Y : P1, T.Y : P2> (Int) -> (@yields @in T)
(%yield, %token) = begin_apply %pa() : $@yield_once @callee_owned @substituted <T where T : P2, T.Y : P1, T.Y : P2> () -> (@yields @in T) for <T>
end_apply %token as $()
%result = tuple ()
return %result : $()
}
// CHECK-LABEL: define {{.*}} void @partial_apply_with_generic_type
// CHECK-SAME: (ptr %[[TY1:.*]], ptr %[[TY2:.*]])
// CHECK: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}})
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[MD_RES:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro18ComplexBoundedTypeVMa"({{i32|i64}} 0, ptr %[[TY1]], ptr %[[TY2]])
// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MD_RES]], 0
// CHECK: store ptr %[[MD]], ptr %[[PA_CTX]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s16generic_functionTA{{.*}}"(ptr noalias {{.*}} %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias {{.*}} %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s16generic_functionTA"
// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s16generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK-32: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [4 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK-64: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[MD:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]])
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @generic_function(ptr noalias {{.*}} %[[FRAMEPTR]], ptr %[[MD]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s16generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s16generic_functionTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
struct ComplexBoundedType<T: P2> {}
sil hidden_external @generic_function : $@yield_once @convention(thin) <T> () -> (@yields @in T)
sil @partial_apply_with_generic_type : $@convention(thin) <U: P2> () -> () {
bb0:
%fn = function_ref @generic_function : $@yield_once @convention(thin) <T> () -> (@yields @in T)
%pa = partial_apply %fn <ComplexBoundedType<U>>() : $@yield_once @convention(thin) <T> () -> (@yields @in T)
(%yield, %token) = begin_apply %pa() : $@yield_once @callee_owned @substituted <T where T: Copyable, T: Escapable> () -> (@yields @in T) for <ComplexBoundedType<U>>
end_apply %token as $()
%result = tuple ()
return %result : $()
}
// Crash on partial apply of a generic enum.
enum GenericEnum<T> {
case X(String)
case Y(T, T, T, T, T)
}
sil public @generic_indirect_return : $@yield_once @convention(thin) <T> (Int) -> @owned GenericEnum<T> {
entry(%i : $Int):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return
// CHECK-SAME: ([[ARG_TYPE:(i32|i64)]] %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}})
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG_PTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG]], ptr %[[PA_ARG_PTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s23generic_indirect_returnTA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
sil @partial_apply_generic_indirect_return : $@convention(thin) (Int) -> @yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> @owned GenericEnum<T> for <Int> {
bb0(%0 : $Int):
%fn = function_ref @generic_indirect_return :$@yield_once @convention(thin) <T> (Int) -> @owned GenericEnum<T>
%pa = partial_apply [callee_guaranteed] %fn<Int> (%0) : $@yield_once @convention(thin) <T> (Int) -> @owned GenericEnum<T>
return %pa : $@yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> @owned GenericEnum<T> for <Int>
}
enum GenericEnum2<T> {
case X(String)
case Y(T)
}
sil public @generic_indirect_return2 : $@yield_once @convention(thin) <T where T: Copyable> (Int) -> @owned GenericEnum2<T> {
entry(%i : $Int):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return2
// CHECK-SAME: ([[ARG_TYPE:(i32|i64)]] %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}})
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG_PTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG]], ptr %[[PA_ARG_PTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s24generic_indirect_return2TA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
sil @partial_apply_generic_indirect_return2 : $@convention(thin) (Int) -> @yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> @owned GenericEnum2<T> for <Int> {
bb0(%0 : $Int):
%fn = function_ref @generic_indirect_return2 :$@yield_once @convention(thin) <T where T: Copyable, T: Escapable> (Int) -> @owned GenericEnum2<T>
%pa = partial_apply [callee_guaranteed] %fn<Int> (%0) : $@yield_once @convention(thin) <T where T: Copyable, T: Escapable> (Int) -> @owned GenericEnum2<T>
return %pa : $@yield_once @callee_guaranteed @substituted <T where T: Copyable, T: Escapable> () -> @owned GenericEnum2<T> for <Int>
}
struct SwiftStruct {}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @fun
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, ptr %1)
sil @fun : $@yield_once @convention(thin) (@thin SwiftStruct.Type, @guaranteed SwiftClass) -> (@yields SwiftStruct, @yields SwiftClass) {
entry(%t : $@thin SwiftStruct.Type, %c : $SwiftClass):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define{{.*}} swiftcc { ptr, ptr } @partial_apply_thin_type
// CHECK-SAME: (ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s3funTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s3funTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @fun(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s3funTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1
// CHECK: ret { ptr, ptr } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s3funTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_thin_type : $@convention(thin) (@thin SwiftStruct.Type, @owned SwiftClass) -> @yield_once @callee_guaranteed () -> (@yields SwiftStruct, @yields SwiftClass) {
entry(%0: $@thin SwiftStruct.Type, %1: $SwiftClass):
%fun = function_ref @fun : $@yield_once @convention(thin) (@thin SwiftStruct.Type, @guaranteed SwiftClass) -> (@yields SwiftStruct, @yields SwiftClass)
%closure = partial_apply [callee_guaranteed] %fun (%0, %1) : $@yield_once @convention(thin) (@thin SwiftStruct.Type, @guaranteed SwiftClass) -> (@yields SwiftStruct, @yields SwiftClass)
return %closure : $@yield_once @callee_guaranteed () -> (@yields SwiftStruct, @yields SwiftClass)
}
struct A1 {
let b: () -> ()
}
struct A2<T> {
let a: T
}
class A3 {}
sil_vtable A3 {}
// CHECK-LABEL: define {{.*}} { ptr, ptr, ptr } @amethod
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, ptr noalias swiftself captures(none) dereferenceable([[SELF_SIZE:(4|8)]]) %1, ptr noalias swifterror captures(none) dereferenceable([[ERROR_SIZE:(4|8)]]) %2)
sil @amethod : $@yield_once @convention(method) (@in_guaranteed A2<A3>) -> (@yields A1, @error Error) {
entry(%a : $*A2<A3>):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @repo
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[SELF_SIZE]]) %[[ARG:.*]])
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s7amethodTA{{.*}}", ptr undef }, ptr %{{.*}}, 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} { ptr, ptr, ptr } @"$s7amethodTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[SELF:.*]], ptr noalias swifterror captures(none) dereferenceable([[ERROR_SIZE]]) %[[ERRORPTR:.*]])
// CHECK: entry:
// CHECK: %[[SELFPTR:.*]] = alloca ptr
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: store ptr %[[SELF]], ptr %[[SELFPTR]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: store ptr null, ptr %[[ERRORPTR]]
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr, ptr } @amethod(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], ptr noalias swiftself captures(none) dereferenceable([[SELF_SIZE]]) %[[SELFPTR]], ptr noalias swifterror captures(none) dereferenceable([[ERROR_SIZE]]) %[[ERRORPTR]])
// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]]
// CHECK: %[[RESUME0:.*]] = extractvalue { ptr, ptr, ptr } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME0]], ptr %[[SPILL2]]
// CHECK: %[[YIELD0:.*]] = extractvalue { ptr, ptr, ptr } %[[YIELD_PAIR]], 1
// CHECK: %[[YIELD1:.*]] = extractvalue { ptr, ptr, ptr } %[[YIELD_PAIR]], 2
// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]]
// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr, ptr } poison, ptr @"$s7amethodTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr, ptr } %[[RET0]], ptr %[[YIELD0]], 1
// CHECK: %[[RET2:.*]] = insertvalue { ptr, ptr, ptr } %[[RET1]], ptr %[[SELF]]0, 2
// CHECK: ret { ptr, ptr, ptr } %[[RET2]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s7amethodTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[ERRORPTR:.*]] = alloca swifterror ptr
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]]
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]]
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]]
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @repo : $@convention(thin) (@in_guaranteed A2<A3>) -> @owned @yield_once @callee_guaranteed () -> (@yields A1, @error Error) {
bb0(%0 : $*A2<A3>):
%1 = load %0 : $*A2<A3>
%2 = alloc_stack $A2<A3>
store %1 to %2 : $*A2<A3>
%4 = function_ref @amethod : $@yield_once @convention(method) (@in_guaranteed A2<A3>) -> (@yields A1, @error Error)
%5 = partial_apply [callee_guaranteed] %4(%2) : $@yield_once @convention(method) (@in_guaranteed A2<A3>) -> (@yields A1, @error Error)
dealloc_stack %2 : $*A2<A3>
return %5 : $@yield_once @callee_guaranteed () -> (@yields A1, @error Error)
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_callee_guaranteed_indirect_guaranteed_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[ARG_SIZE:(8|16)]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: call void @llvm.memcpy.p0.p0.{{i32|i64}}(ptr align {{4|8}} %[[BOXPTR]], ptr align {{4|8}} %[[ARG]], {{i32|i64}} [[ARG_SIZE]], i1 false)
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"
// CHECK-SAME:(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE:(i32|i64)]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[PA_ARG]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[PA_ARG]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable({{8|16}}) %[[PA_CTX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]],
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_callee_guaranteed_indirect_guaranteed_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> @owned @yield_once @callee_guaranteed (Int) -> (@yields Int) {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
return %p : $@yield_once @callee_guaranteed(Int) -> (@yields Int)
}
sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
// CHECK-LABEL: define {{.*}} @partial_apply_stack_callee_guaranteed_indirect_guaranteed_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[ARG_SIZE:(8|16)]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[BOX:.*]] = alloca i8
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[RES_TYPE:(i32|i64)]] } @use_closure2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}{{.*}}", ptr %[[BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[RES_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[RES_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: ret void
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE:(i32|i64)]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable({{8|16}}) %[[PA_ARG]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_stack_callee_guaranteed_indirect_guaranteed_class_pair_param : $@convention(thin) (@in_guaranteed SwiftClassPair) -> () {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_guaranteed_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] [on_stack] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%u = function_ref @use_closure2 : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
(%i, %token) = begin_apply %u(%p) : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
end_apply %token as $()
dealloc_stack %p : $@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)
%t = tuple()
return %t : $()
}
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @indirect_in_captured_class_pair_param
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @indirect_in_captured_class_pair_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, [[ARG_TYPE:(i32|i64)]] %{{.*}}, ptr noalias captures(none) dereferenceable([[PAIR_SIZE:(8|16)]]) %{{.*}})
sil public @indirect_in_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int) {
entry(%i : $Int, %p : $*SwiftClassPair):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8],
// CHECK: %[[BOX:.*]] = alloca i8
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @use_closure2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr @"$s37indirect_in_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]])
// CHECK: ret void
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s37indirect_in_captured_class_pair_paramTA"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s37indirect_in_captured_class_pair_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s37indirect_in_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_in_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[PA_ARG]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s37indirect_in_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s37indirect_in_captured_class_pair_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s37indirect_in_captured_class_pair_paramTA.resume.0"
// CHECK-SAME: (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s37indirect_in_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s37indirect_in_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1]] = getelementptr inbounds %"$s37indirect_in_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_stack_callee_guaranteed_indirect_in_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> () {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_in_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] [on_stack] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%u = function_ref @use_closure2 : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
(%r, %token) = begin_apply %u(%p) : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
end_apply %token as $()
dealloc_stack %p : $@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)
destroy_addr %x: $*SwiftClassPair
%t = tuple()
return %t : $()
}
// CHECK-LABEL: define {{.*}} void @test_initial_offset
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s16resilient_struct12ResilientIntVMa"
// CHECK: [[MD:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
// CHECK: [[VWT_PTR:%.*]] = getelementptr inbounds ptr, ptr [[MD]], {{i32|i64}} -1
// CHECK: [[VWTABLE:%.*]] = load ptr, ptr [[VWT_PTR]]
// CHECK-arm64e: [[VWTABLEADDR:%.*]] = ptrtoint ptr [[VWT_PTR]] to i64
// CHECK-arm64e: [[VWTABLEAUTH:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VWTABLEADDR]], i32 2
// CHECK-arm64e: [[VWTABLE:%.*]] = inttoptr i64 [[VWTABLEAUTH]] to ptr
// CHECK: [[FLAGS_PTR:%.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr [[VWTABLE]], i32 0, i32 10
sil public_external @closure : $@yield_once @convention(thin) (@in_guaranteed ResilientInt, @guaranteed SwiftClass) -> (@yields @in ResilientInt)
sil @test_initial_offset : $@convention(thin) (@in ResilientInt, @guaranteed SwiftClass) -> () {
bb0(%x : $*ResilientInt, %y : $SwiftClass):
%f = function_ref @closure : $@yield_once @convention(thin) (@in_guaranteed ResilientInt, @guaranteed SwiftClass) -> (@yields @in ResilientInt)
%p = partial_apply [callee_guaranteed] %f(%x, %y) : $@yield_once @convention(thin) (@in_guaranteed ResilientInt, @guaranteed SwiftClass) -> (@yields @in ResilientInt)
(%yield, %token) = begin_apply %p() : $@yield_once @callee_guaranteed () -> (@yields @in ResilientInt)
end_apply %token as $()
release_value %p : $@yield_once @callee_guaranteed () -> (@yields @in ResilientInt)
%t = tuple()
return %t : $()
}
protocol Proto1 {}
protocol Proto2 {}
struct EmptyType : Proto1 { }
struct SomeType : Proto2 {
var d : ResilientInt // some resilient type
var x : Int
}
// CHECK-64-LABEL: define{{.*}} swiftcc void @empty_followed_by_non_fixed(ptr noalias %0)
// CHECK-64: [[FLAGS:%.*]] = load i32, ptr
// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64
// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255
// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1
// Make sure we take the header offset (16) into account.
// CHECK-64: [[TMP:%.*]] = add i64 16, [[ALIGNMASK]]
// CHECK-64: [[OFFSET:%.*]] = and i64 [[TMP]], [[NOTALIGNMASK]]
// CHECK-64: [[CONTEXT:%.*]] = call noalias ptr @swift_allocObject
// CHECK-64: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[CONTEXT]], i64 [[OFFSET]]
// CHECK-64: call ptr @"$s18partial_apply_coro8SomeTypeVWOb"(ptr {{.*}}, ptr [[GEP]])
sil @foo : $@yield_once @convention(thin) <T0, T1 where T0 : Proto1, T1 : Proto2> (@in_guaranteed T0, @in_guaranteed T1) -> (@yields @in T0, @yields @in T1)
sil @empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType) -> () {
entry(%0 : $EmptyType, %1: $*SomeType):
%5 = alloc_stack $EmptyType
store %0 to %5 : $*EmptyType
%31 = function_ref @foo : $@yield_once @convention(thin) <T0, T1 where T0 : Proto1, T1 : Proto2> (@in_guaranteed T0, @in_guaranteed T1) -> (@yields @in T0, @yields @in T1)
%32 = alloc_stack $EmptyType
copy_addr %5 to [init] %32 : $*EmptyType
%34 = alloc_stack $SomeType
copy_addr %1 to [init] %34 : $*SomeType // id: %35
%36 = partial_apply [callee_guaranteed] %31<EmptyType, SomeType>(%32, %34) : $@yield_once @convention(thin) <T0, T1 where T0 : Proto1, T1 : Proto2> (@in_guaranteed T0, @in_guaranteed T1) -> (@yields @in T0, @yields @in T1)
(%yield1, %yield2, %token) = begin_apply %36() : $@yield_once @callee_guaranteed @substituted <T0, T1 where T0 : Proto1, T1 : Proto2> () -> (@yields @in T0, @yields @in T1) for <EmptyType, SomeType>
end_apply %token as $()
release_value %36: $@yield_once @callee_guaranteed @substituted <T0, T1 where T0 : Proto1, T1 : Proto2> () -> (@yields @in T0, @yields @in T1) for <EmptyType, SomeType>
dealloc_stack %34 : $*SomeType
dealloc_stack %32 : $*EmptyType
dealloc_stack %5 : $*EmptyType
%40 = tuple()
return %40 : $()
}
// CHECK-64-LABEL: define{{.*}} swiftcc void @fixed_followed_by_empty_followed_by_non_fixed
// CHECK-64-NOT: ret
// CHECK-64: [[FLAGS:%.*]] = load i32, ptr
// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64
// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255
// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1
// Make sure we compute the correct offset of the non-fixed field.
// CHECK-64: [[TMP:%.*]] = add i64 20, [[ALIGNMASK]]
// CHECK-64: ret
struct FixedType {
var f: Int32
}
sil @foo2 : $@yield_once @convention(thin) <T0, T1, T2> (@in_guaranteed T0, @in_guaranteed T1, @in_guaranteed T2) -> (@yields @in T0, @out T1, @out T2)
sil @fixed_followed_by_empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType, FixedType) -> () {
entry(%0 : $EmptyType, %1: $*SomeType, %3: $FixedType):
%5 = alloc_stack $EmptyType
store %0 to %5 : $*EmptyType
%7 = alloc_stack $FixedType
store %3 to %7 : $*FixedType
%31 = function_ref @foo2 : $@yield_once @convention(thin) <T0, T1, T2> (@in_guaranteed T0, @in_guaranteed T1, @in_guaranteed T2) -> (@yields @in T0, @out T1, @out T2)
%32 = alloc_stack $EmptyType
copy_addr %5 to [init] %32 : $*EmptyType
%34 = alloc_stack $SomeType
copy_addr %1 to [init] %34 : $*SomeType // id: %35
%36 = partial_apply [callee_guaranteed] %31<FixedType, EmptyType, SomeType>(%7, %32, %34) : $@yield_once @convention(thin) <T0, T1, T2> (@in_guaranteed T0, @in_guaranteed T1, @in_guaranteed T2) -> (@yields @in T0, @out T1, @out T2)
release_value %36: $@yield_once @callee_guaranteed @substituted <T0, T1, T2 where T0: Copyable, T0: Escapable, T1: Copyable, T1: Escapable, T2: Copyable, T2: Escapable> () -> (@yields @in T0, @out T1, @out T2) for <FixedType, EmptyType, SomeType>
dealloc_stack %34 : $*SomeType
dealloc_stack %32 : $*EmptyType
dealloc_stack %7 : $*FixedType
dealloc_stack %5 : $*EmptyType
%40 = tuple()
return %40 : $()
}
// Test that we don't have an alloc object with 0, because that is not allowed
// CHECK-LABEL: define{{.*}} swiftcc void @my_test_case
// CHECK-NOT: swift_allocObject
// CHECK: ret
sil @take_empty : $@yield_once @convention(thin) (@in_guaranteed EmptyType) -> (@yields EmptyType)
sil @my_test_case : $@convention(thin) () -> () {
entry:
%5 = alloc_stack $EmptyType
// store % to %5
%f = function_ref @take_empty : $@yield_once @convention(thin) (@in_guaranteed EmptyType) -> (@yields EmptyType)
%36 = partial_apply [callee_guaranteed] %f(%5) : $@yield_once @convention(thin) (@in_guaranteed EmptyType) -> (@yields EmptyType)
release_value %36: $@yield_once @callee_guaranteed () -> (@yields EmptyType)
dealloc_stack %5 : $*EmptyType
%t = tuple()
return %t : $()
}
// CHECK-32: define {{.*}} { ptr, i32 } @indirect_in_constant_captured_class_pair_param
// CHECK-64: define {{.*}} { ptr, i64 } @indirect_in_constant_captured_class_pair_param
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, [[ARG_TYPE:(i32|i64)]] %1, ptr noalias captures(none) dereferenceable([[PAIR_SIZE:(8|16)]]) %2)
sil public @indirect_in_constant_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int) {
entry(%i : $Int, %ic : $*SwiftClassPair):
%0 = builtin "int_trap"() : $Never
unreachable
}
// CHECK-LABEL: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_constant_class_pair_param
// CHECK-SAME: (ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8]
// CHECK: %[[BOX:.*]] = alloca i8
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1
// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]]
// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[CTX]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @use_closure2(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], ptr @"$s46indirect_in_constant_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTXPTR]], i1 false)
// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]])
// CHECK: call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]])
// CHECK: ret void
// CHECK: }
//
// CHECK-32-LABEL: define {{.*}} { ptr, i32 } @"$s46indirect_in_constant_captured_class_pair_paramTA"
// CHECK-64-LABEL: define {{.*}} { ptr, i64 } @"$s46indirect_in_constant_captured_class_pair_paramTA"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s46indirect_in_constant_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG:.*]] = load ptr, ptr %[[PA_CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, [[ARG_TYPE]] } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG0]], ptr noalias captures(none) dereferenceable([[PAIR_SIZE]]) %[[PA_ARG]])
// CHECK: %[[RESUME:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 0
// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s46indirect_in_constant_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]]
// CHECK: %[[YIELD:.*]] = extractvalue { ptr, [[ARG_TYPE]] } %[[YIELD_PAIR]], 1
// CHECK: %[[RET0:.*]] = insertvalue { ptr, [[ARG_TYPE]] } poison, ptr @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0", 0
// CHECK: %[[RET1:.*]] = insertvalue { ptr, [[ARG_TYPE]] } %[[RET0]], [[ARG_TYPE]] %[[YIELD]], 1
// CHECK: ret { ptr, [[ARG_TYPE]] } %[[RET1]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} void @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0"
// CHECK-SAMEL (ptr noalias noundef nonnull align {{4|8}} dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]])
// CHECK: entryresume.0:
// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s46indirect_in_constant_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0
// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume
//
// CHECK-LABEL: unwind:
// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s46indirect_in_constant_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]]
// CHECK: %[[CTX0:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX0]], i1 true)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: unreachable
//
// CHECK-LABEL: resume:
// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s46indirect_in_constant_captured_class_pair_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1
// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]]
// CHECK: %[[CTX1:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAMEPTR]], i32 0, i32 0
// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX1]], i1 false)
// CHECK: call void @free(ptr %[[FRAME]])
// CHECK: ret void
// CHECK: }
//
sil @partial_apply_stack_callee_guaranteed_indirect_in_constant_class_pair_param : $@convention(thin) (@in SwiftClassPair) -> () {
bb0(%x : $*SwiftClassPair):
%f = function_ref @indirect_in_constant_captured_class_pair_param : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%p = partial_apply [callee_guaranteed] [on_stack] %f(%x) : $@yield_once @convention(thin) (Int, @in_guaranteed SwiftClassPair) -> (@yields Int)
%u = function_ref @use_closure2 : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
(%r, %token) = begin_apply %u(%p) : $@yield_once @convention(thin) (@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)) -> (@yields Int)
end_apply %token as $()
dealloc_stack %p : $@noescape @yield_once @callee_guaranteed (Int) -> (@yields Int)
destroy_addr %x: $*SwiftClassPair
%t = tuple()
return %t : $()
}
sil @create_pa_f2 : $@convention(thin) (@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) -> Int64, Int32) -> @owned @yield_once @callee_guaranteed (Int64) -> Int64 {
bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) -> Int64 , %captured : $Int32):
%pa_f = partial_apply [callee_guaranteed] %thick(%captured) : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) -> Int64
%pa_f2 = partial_apply [callee_guaranteed] %thick(%captured) : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) -> Int64
return %pa_f : $@yield_once @callee_guaranteed (Int64) -> Int64
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @dont_crash
// CHECK-SAME: ([[ARG_TYPE:(i64|i32)]] %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata
// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi }>, ptr %1, i32 0, i32 1
// CHECK: %[[ARGPTR:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %2, i32 0, i32 0
// CHECK: store [[ARG_TYPE]] %[[ARG]], ptr %[[ARGPTR]]
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s16external_closureTA{{.*}}", ptr undef }, ptr %[[BOX]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
//
// CHECK-LABEL: define {{.*}} ptr @"$s16external_closureTA"
// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], [[ARG_TYPE]] %[[ARG1:.*]], ptr swiftself %[[PA_CTX_BOX:.*]], ptr noalias swifterror captures(none) {{.*}} %[[ERROR:.*]])
// CHECK: entry:
// CHECK: %[[SPILL:.*]] = call ptr @malloc
// CHECK: store ptr %[[SPILL]], ptr %[[CTX]]
// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s16external_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 0
// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds{{.*}} <{ %swift.refcounted, %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1
// CHECK: %[[PA_ARG:.*]] = getelementptr inbounds{{.*}} %TSi, ptr %[[PA_CTX]], i32 0, i32 0
// CHECK: %[[ARG2:.*]] = load [[ARG_TYPE]], ptr %[[PA_ARG]]
// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds{{.*}} [[[BUFFER_SIZE]] x i8], ptr %[[FRAME]], i32 0, i32 0
// CHECK: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr %[[FRAMEPTR]])
// CHECK: store ptr null, ptr %[[ERROR]]
// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc ptr @external_closure(ptr noalias {{.*}} %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG1]], [[ARG_TYPE]] %[[ARG2]], ptr swiftself undef, ptr noalias swifterror captures(none) {{.*}} %[[ERROR]])
// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %"$s16external_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 1
// CHECK: store ptr %[[YIELD_PAIR]], ptr %[[SPILL1]]
// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERROR]]
// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERROR]]
// CHECK: ret ptr @"$s16external_closureTA.resume.0"
// CHECK: }
//
sil @external_closure : $@convention(thin) @yield_once (Int, Int) -> (Int, @error Error)
sil @dont_crash : $@convention(thin) (Int) -> @owned @yield_once @callee_guaranteed (Int) -> (Int, @error Error) {
bb0(%0 : $Int):
%2 = function_ref @external_closure : $@convention(thin) @yield_once (Int, Int) -> (Int, @error Error)
%3 = partial_apply [callee_guaranteed] %2(%0) : $@convention(thin) @yield_once (Int, Int) -> (Int, @error Error)
return %3 : $@yield_once @callee_guaranteed (Int) -> (Int, @error Error)
}
// CHECK-LABEL: define {{.*}} { ptr, ptr } @partially_apply_method_with_out_return
// CHECK-SAME: (ptr %[[ARG:.*]])
// CHECK: entry:
// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s22method_with_out_returnTA{{.*}}", ptr undef }, ptr %[[ARG]], 1
// CHECK: ret { ptr, ptr } %[[RET]]
// CHECK: }
sil @method_with_out_return : $@convention(method) @yield_once (SwiftClass) -> @out Int
sil @partially_apply_method_with_out_return : $@convention(thin) (SwiftClass) -> @yield_once @callee_guaranteed () -> @out Int {
bb(%class : $SwiftClass):
%method_with_out_param = function_ref @method_with_out_return : $@convention(method) @yield_once (SwiftClass) -> @out Int
%result = partial_apply [callee_guaranteed] %method_with_out_param(%class) : $@convention(method) @yield_once (SwiftClass) -> @out Int
return %result : $@callee_guaranteed @yield_once () -> @out Int
}