diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 3c38b98f7ba44..6504ab41d269a 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -488,6 +488,9 @@ class IRGenOptions { unsigned EmitAsyncFramePushPopMetadata : 1; + // Whether to emit typed malloc during coroutine frame allocation. + unsigned EmitTypeMallocForCoroFrame : 1; + // Whether to use the yield_once ABI when emitting yield_once_2 coroutines. unsigned EmitYieldOnce2AsYieldOnce : 1; @@ -597,8 +600,9 @@ class IRGenOptions { DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false), ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false), UseFragileResilientProtocolWitnesses(false), EnableHotColdSplit(false), - EmitAsyncFramePushPopMetadata(true), EmitYieldOnce2AsYieldOnce(true), - AsyncFramePointerAll(false), UseProfilingMarkerThunks(false), + EmitAsyncFramePushPopMetadata(true), EmitTypeMallocForCoroFrame(false), + EmitYieldOnce2AsYieldOnce(true), AsyncFramePointerAll(false), + UseProfilingMarkerThunks(false), DebugInfoForProfiling(false), CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()), TypeInfoFilter(TypeInfoDumpFilter::All), diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index e47dee812157e..31a743faecba0 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -1341,6 +1341,13 @@ def disable_async_frame_push_pop_metadata : Flag<["-"], "disable-async-frame-push-pop-metadata">, HelpText<"Disable async frame push pop metadata">; +def enable_emit_type_malloc_for_coro_frame : + Flag<["-"], "enable-emit-type-malloc-for-coro-frame">, + HelpText<"Enable emitting typed malloc for coroutine frame allocation">; +def disable_emit_type_malloc_for_coro_frame : + Flag<["-"], "disable-emit-type-malloc-for-coro-frame">, + HelpText<"Disable emitting typed malloc for coroutine frame allocation">; + def enable_async_frame_pointer_all : Flag<["-"], "enable-async-frame-pointer-all">, HelpText<"Always emit async frame stack frames (frame-pointer=all)">; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e027d1181736b..87f2dd87ea4a7 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -3627,6 +3627,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, Args.hasFlag(OPT_enable_async_frame_push_pop_metadata, OPT_disable_async_frame_push_pop_metadata, Opts.EmitAsyncFramePushPopMetadata); + Opts.EmitTypeMallocForCoroFrame = + Args.hasFlag(OPT_enable_emit_type_malloc_for_coro_frame, + OPT_disable_emit_type_malloc_for_coro_frame, + Opts.EmitTypeMallocForCoroFrame); Opts.AsyncFramePointerAll = Args.hasFlag(OPT_enable_async_frame_pointer_all, OPT_disable_async_frame_pointer_all, Opts.AsyncFramePointerAll); diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 903b05725fe30..a30f7876f61ef 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -4822,20 +4822,41 @@ emitRetconCoroutineEntry(IRGenFunction &IGF, CanSILFunctionType fnType, auto prototype = IGF.IGM.getOpaquePtr(IGF.IGM.getAddrOfContinuationPrototype(fnType)); - // Use malloc and free as our allocator. - auto allocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getMallocFn()); + + + // Use free as our deallocator. auto deallocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getFreeFn()); // Call the right 'llvm.coro.id.retcon' variant. llvm::Value *buffer = emission.getCoroutineBuffer(); - llvm::Value *id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, { - llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()), - llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()), - buffer, - prototype, - allocFn, - deallocFn - }); + + llvm::Value *id; + if (IGF.getOptions().EmitTypeMallocForCoroFrame) { + // Use swift_coroFrameAlloc as our allocator. + auto coroAllocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getCoroFrameAllocFn()); + auto mallocTypeId = IGF.getMallocTypeId(); + id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, { + llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()), + llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()), + buffer, + prototype, + coroAllocFn, + deallocFn, + mallocTypeId + }); + } else { + // Use mallocas our allocator. + auto allocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getMallocFn()); + id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, { + llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()), + llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()), + buffer, + prototype, + allocFn, + deallocFn + }); + } + // Call 'llvm.coro.begin', just for consistency with the normal pattern. // This serves as a handle that we can pass around to other intrinsics. diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 5545b2b6bcf1e..d4f0900e2bcaf 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1459,13 +1459,30 @@ class CoroPartialApplicationForwarderEmission cast( unsubstType->mapTypeOutOfContext()->getCanonicalType()))); - // Use malloc and free as our allocator. - auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn()); + + // Use free as our allocator. auto deallocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getFreeFn()); // Call the right 'llvm.coro.id.retcon' variant. llvm::Value *buffer = origParams.claimNext(); - llvm::Value *id = subIGF.Builder.CreateIntrinsicCall( + llvm::Value *id; + if (subIGF.IGM.getOptions().EmitTypeMallocForCoroFrame) { + // Use swift_coroFrameAlloc as our allocator. + auto coroAllocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getCoroFrameAllocFn()); + auto mallocTypeId = subIGF.getMallocTypeId(); + id = subIGF.Builder.CreateIntrinsicCall( + llvm::Intrinsic::coro_id_retcon_once, + {llvm::ConstantInt::get( + subIGF.IGM.Int32Ty, + getYieldOnceCoroutineBufferSize(subIGF.IGM).getValue()), + llvm::ConstantInt::get( + subIGF.IGM.Int32Ty, + getYieldOnceCoroutineBufferAlignment(subIGF.IGM).getValue()), + buffer, prototype, coroAllocFn, deallocFn, mallocTypeId}); + } else { + // Use malloc as our allocator. + auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn()); + id = subIGF.Builder.CreateIntrinsicCall( llvm::Intrinsic::coro_id_retcon_once, {llvm::ConstantInt::get( subIGF.IGM.Int32Ty, @@ -1474,6 +1491,7 @@ class CoroPartialApplicationForwarderEmission subIGF.IGM.Int32Ty, getYieldOnceCoroutineBufferAlignment(subIGF.IGM).getValue()), buffer, prototype, allocFn, deallocFn}); + } // Call 'llvm.coro.begin', just for consistency with the normal pattern. // This serves as a handle that we can pass around to other intrinsics. diff --git a/lib/IRGen/GenPointerAuth.cpp b/lib/IRGen/GenPointerAuth.cpp index e71e2895497d3..5a47e225ba360 100644 --- a/lib/IRGen/GenPointerAuth.cpp +++ b/lib/IRGen/GenPointerAuth.cpp @@ -767,3 +767,7 @@ void ConstantAggregateBuilderBase::addSignedPointer(llvm::Constant *pointer, addSignedPointer(pointer, schema.getKey(), schema.isAddressDiscriminated(), llvm::ConstantInt::get(IGM().Int64Ty, otherDiscriminator)); } + +llvm::ConstantInt* IRGenFunction::getMallocTypeId() { + return getDiscriminatorForString(IGM, CurFn->getName()); +} diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index e77b45362ee4e..830ece37749df 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -142,6 +142,8 @@ class IRGenFunction { Address getCalleeTypedErrorResultSlot(SILType errorType); void setCalleeTypedErrorResultSlot(Address addr); + llvm::ConstantInt* getMallocTypeId(); + /// Are we currently emitting a coroutine? bool isCoroutine() { return CoroutineHandle != nullptr; diff --git a/test/IRGen/yield_once.sil b/test/IRGen/yield_once.sil index f3282a6ef4e76..8d9886aa6a51d 100644 --- a/test/IRGen/yield_once.sil +++ b/test/IRGen/yield_once.sil @@ -10,8 +10,8 @@ sil @marker : $(Builtin.Int32) -> () // CHECK-SAME: [[CORO_ATTRIBUTES:#[0-9]+]] sil @test_simple : $@yield_once () -> () { entry: - // CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free) + // CHECK-32: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: call swiftcc void @marker(i32 1000) diff --git a/test/IRGen/yield_once_big.sil b/test/IRGen/yield_once_big.sil index 8090e887a6320..2d516e42a5eae 100644 --- a/test/IRGen/yield_once_big.sil +++ b/test/IRGen/yield_once_big.sil @@ -44,8 +44,8 @@ entry: // CHECK-64-SAME: , align 8 // Coroutine setup. - // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) - // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) + // CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) + // CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr @@ -181,8 +181,8 @@ entry(%arg : $*BigWrapper): // CHECK-64-SAME: , align 8 // Coroutine setup. - // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free) - // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free) + // CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free) + // CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr diff --git a/test/IRGen/yield_once_biggish.sil b/test/IRGen/yield_once_biggish.sil index 72e09248f110f..8efd45f0033d1 100644 --- a/test/IRGen/yield_once_biggish.sil +++ b/test/IRGen/yield_once_biggish.sil @@ -40,8 +40,8 @@ entry: // CHECK-64-SAME: , align 8 // Coroutine setup. - // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free) - // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free) + // CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free) + // CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr // CHECK-NEXT: call swiftcc void @marker(i32 1000) diff --git a/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil new file mode 100644 index 0000000000000..50af74df873ce --- /dev/null +++ b/test/IRGen/yield_once_enable_emit_type_malloc_coro_frame.sil @@ -0,0 +1,135 @@ +// RUN: %target-swift-frontend -emit-irgen -enable-emit-type-malloc-for-coro-frame %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-ptrsize-%target-ptrauth + +import Builtin + +sil @marker : $(Builtin.Int32) -> () + +// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @test_simple +// CHECK-32-SAME: ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %0) +// CHECK-64-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %0) +// CHECK-SAME: [[CORO_ATTRIBUTES:#[0-9]+]] +sil @test_simple : $@yield_once () -> () { +entry: + // CHECK-32: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sIetA_TC", ptr @swift_coroFrameAlloc, ptr @free, i64 38223) + // CHECK-64: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sIetA_TC", ptr @swift_coroFrameAlloc, ptr @free, i64 38223) + // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) + + // CHECK-NEXT: call swiftcc void @marker(i32 1000) + %marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> () + %1000 = integer_literal $Builtin.Int32, 1000 + apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> () + + // CHECK-NEXT: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1() + // CHECK-NEXT: br i1 [[IS_UNWIND]] + yield (), resume resume, unwind unwind + +resume: + // CHECK: call swiftcc void @marker(i32 2000) + %2000 = integer_literal $Builtin.Int32, 2000 + apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> () + // CHECK: br label %coro.end + %ret = tuple () + return %ret : $() + +unwind: + // CHECK: call swiftcc void @marker(i32 3000) + %3000 = integer_literal $Builtin.Int32, 3000 + apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> () + // CHECK: br label %coro.end + unwind + + // CHECK: coro.end: + // CHECK: call i1 @llvm.coro.end(ptr [[BEGIN]], i1 false, token none) + // CHECK-NEXT: unreachable +} + +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$sIetA_TC" +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) + +// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) +sil @test_simple_call : $(Builtin.Int1) -> () { +entry(%flag : $Builtin.Int1): + // Allocate the buffer. + // CHECK: [[T0:%.*]] = alloca {{\[}}[[BUFFER_SIZE]] x i8], align [[BUFFER_ALIGN]] + // CHECK-NEXT: [[BUFFER:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE]] x i8], ptr [[T0]], i32 0, i32 0 + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]]) + + // Prepare the continuation function pointer to block analysis. + // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @test_simple) + // Call the function pointer. + // CHECK-NEXT: [[CONTINUATION:%.*]] = call swiftcc ptr [[T0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]]) + %0 = function_ref @test_simple : $@convention(thin) @yield_once () -> () + %token = begin_apply %0() : $@convention(thin) @yield_once () -> () + + // Branch. + // CHECK-NEXT: br i1 %0, + cond_br %flag, yes, no + +yes: + // CHECK-64-ptrauth: ptrtoint + // CHECK-64-ptrauth-NEXT: ptrauth.blend + // CHECK: call swiftcc void [[CONTINUATION]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 false) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]]) + end_apply %token as $() + + // CHECK-NEXT: br label + br cont + +no: + // CHECK-64-ptrauth: ptrtoint + // CHECK-64-ptrauth-NEXT: ptrauth.blend + // CHECK: call swiftcc void [[CONTINUATION]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 true) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]]) + abort_apply %token + + // CHECK-NEXT: br label + br cont + +cont: + // CHECK: ret void + %ret = tuple () + return %ret : $() +} + +sil @yields_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32) + +// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_yields_pair() +sil @test_yields_pair : $() -> () { +entry: + %marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> () + + // Allocate the buffer. + // CHECK: [[T0:%.*]] = alloca {{\[}}[[BUFFER_SIZE]] x i8], align [[BUFFER_ALIGN]] + // CHECK-NEXT: [[BUFFER:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE]] x i8], ptr [[T0]], i32 0, i32 0 + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]]) + + // Prepare the continuation function pointer to block analysis. + // CHECK-NEXT: [[T0:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @yields_pair) + // Call the function pointer. + // CHECK-NEXT: [[PACKED:%.*]] = call swiftcc { ptr, i32, i32 } [[T0]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]]) + // CHECK-NEXT: [[CONTINUATION:%.*]] = extractvalue { ptr, i32, i32 } [[PACKED]], 0 + // CHECK-NEXT: [[FIRST:%.*]] = extractvalue { ptr, i32, i32 } [[PACKED]], 1 + // CHECK-NEXT: [[SECOND:%.*]] = extractvalue { ptr, i32, i32 } [[PACKED]], 2 + %coro = function_ref @yields_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32) + (%first, %second, %token) = begin_apply %coro() : $@yield_once @convention(thin) () -> (@yields Builtin.Int32, @yields Builtin.Int32) + + // CHECK-NEXT: call swiftcc void @marker(i32 [[FIRST]]) + apply %marker(%first) : $@convention(thin) (Builtin.Int32) -> () + + // CHECK-64-ptrauth-NEXT: ptrtoint + // CHECK-64-ptrauth-NEXT: ptrauth.blend + // CHECK-NEXT: call swiftcc void [[CONTINUATION]](ptr noalias dereferenceable([[BUFFER_SIZE]]) [[BUFFER]], i1 false) + // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr [[BUFFER]]) + end_apply %token as $() + + // CHECK-NEXT: call swiftcc void @marker(i32 [[SECOND]]) + apply %marker(%second) : $@convention(thin) (Builtin.Int32) -> () + + // CHECK-NEXT: ret void + %ret = tuple () + return %ret : $() +} + + +// CHECK: attributes [[CORO_ATTRIBUTES]] = +// CHECK-SAME: noinline diff --git a/test/IRGen/yield_once_indirect.sil b/test/IRGen/yield_once_indirect.sil index 28af3ed2389c7..331bfe82604fc 100644 --- a/test/IRGen/yield_once_indirect.sil +++ b/test/IRGen/yield_once_indirect.sil @@ -30,8 +30,8 @@ entry: // CHECK-64-SAME: , align 8 // Coroutine setup. - // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) - // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) + // CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) + // CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr // CHECK-NEXT: call swiftcc void @marker(i32 1000) diff --git a/test/IRGen/yield_result.sil b/test/IRGen/yield_result.sil index 1d380d620948a..30ecd8b2bf47e 100644 --- a/test/IRGen/yield_result.sil +++ b/test/IRGen/yield_result.sil @@ -13,9 +13,9 @@ sil @coro_ret_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int64 // CHECK-SAME: [[CORO_ATTRIBUTES:#[0-9]+]] sil @test_simple : $@yield_once () -> (Builtin.Int64) { entry: - // CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) - // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) + // CHECK-32: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) + // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: call swiftcc void @marker(i64 1000) %marker = function_ref @marker : $@convention(thin) (Builtin.Int64) -> () @@ -98,8 +98,8 @@ entry: // CHECK-SAME: ptr{{.*}} [[CTX:%.*]], ptr{{.*}} [[INDIRECT_RET:%.*]], ptr{{.*}} [[ARG:%.*]], ptr{{.*}} [[TYPE:%.*]]) sil @coro_ret_indirect : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) { bb0(%outt : $*T, %t : $*T): - // CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) + // CHECK-32: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free) // CHECK: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[ARG]]) // CHECK: br i1 [[IS_UNWIND]], label %[[UNWIND_BB:.*]], label %[[RESUME_BB:.*]]