From 6d909aa70f70302077ae1017e889f336450bb85c Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Mon, 25 Sep 2023 12:38:27 +0900 Subject: [PATCH 01/12] Partial apply for coroutines The patch adds lowering of partial_apply instructions for coroutines. This pattern seems to trigger a lot of type mismatch errors in IRGen, because coroutine functions are not substituted in the same way as regular functions (see the patch 07f03bd2 "Use pattern substitutions to consistently abstract yields" for more details). The odd type conversions in the patch are related to this issue, and these should be checked carefully. Perhaps it is better to enable substitutions for coroutine functions instead (at least for some cases). Other than that, lowering of partial_apply for coroutines is straightforward: we generate another coroutine that captures arguments passed to the partial_apply instructions. It calls the original coroutine for yields (first return) and yields the resulting values. Then it calls the original function's continuation for return or unwind, and forwards them to the caller as well. After IRGen, LLVM's Coroutine pass transforms the generated coroutine (along with all other coroutines) and eliminates llvm.coro.* intrinsics. LIT tests check LLVM IR after this transformation. --- lib/IRGen/GenDecl.cpp | 1 + lib/IRGen/GenFunc.cpp | 278 ++++- lib/IRGen/IRGenSIL.cpp | 8 +- test/IRGen/partial_apply_coro.sil | 1943 +++++++++++++++++++++++++++++ 4 files changed, 2214 insertions(+), 16 deletions(-) create mode 100644 test/IRGen/partial_apply_coro.sil diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index f5b118f878057..d7b65ebbbf4a4 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -6163,6 +6163,7 @@ IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) { llvm::Function *&entry = GlobalFuncs[entity]; if (entry) return entry; + GenericContextScope scope(*this, fnType->getInvocationGenericSignature()); auto signature = Signature::forCoroutineContinuation(*this, fnType); LinkInfo link = LinkInfo::get(*this, entity, NotForDefinition); entry = createFunction(*this, link, signature); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 56b06e8fa132e..041510ceb6893 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -91,6 +91,7 @@ #include "llvm/Support/Debug.h" #include "BitPatternBuilder.h" +#include "CallEmission.h" #include "Callee.h" #include "ConstantBuilder.h" #include "EnumPayload.h" @@ -109,11 +110,11 @@ #include "HeapTypeInfo.h" #include "IRGenDebugInfo.h" #include "IRGenFunction.h" +#include "IRGenMangler.h" #include "IRGenModule.h" #include "IndirectTypeInfo.h" #include "ScalarPairTypeInfo.h" #include "Signature.h" -#include "IRGenMangler.h" using namespace swift; using namespace irgen; @@ -1119,11 +1120,11 @@ class PartialApplicationForwarderEmission { virtual void addDynamicFunctionContext(Explosion &explosion) = 0; virtual void addDynamicFunctionPointer(Explosion &explosion) = 0; - void addSelf(Explosion &explosion) { addArgument(explosion); } - void addWitnessSelfMetadata(llvm::Value *value) { + virtual void addSelf(Explosion &explosion) { addArgument(explosion); } + virtual void addWitnessSelfMetadata(llvm::Value *value) { addArgument(value); } - void addWitnessSelfWitnessTable(llvm::Value *value) { + virtual void addWitnessSelfWitnessTable(llvm::Value *value) { addArgument(value); } virtual void forwardErrorResult() = 0; @@ -1136,6 +1137,14 @@ class PartialApplicationForwarderEmission { virtual void end(){}; virtual ~PartialApplicationForwarderEmission() {} }; + +static Size getYieldOnceCoroutineBufferSize(IRGenModule &IGM) { + return NumWords_YieldOnceBuffer * IGM.getPointerSize(); +} +static Alignment getYieldOnceCoroutineBufferAlignment(IRGenModule &IGM) { + return IGM.getPointerAlignment(); +} + class SyncPartialApplicationForwarderEmission : public PartialApplicationForwarderEmission { using super = PartialApplicationForwarderEmission; @@ -1422,6 +1431,239 @@ class AsyncPartialApplicationForwarderEmission super::end(); } }; + +class CoroPartialApplicationForwarderEmission + : public PartialApplicationForwarderEmission { + using super = PartialApplicationForwarderEmission; + +private: + llvm::Value *Self; + llvm::Value *FirstData; + llvm::Value *SecondData; + WitnessMetadata Witness; + +public: + CoroPartialApplicationForwarderEmission( + IRGenModule &IGM, IRGenFunction &subIGF, llvm::Function *fwd, + const std::optional &staticFnPtr, bool calleeHasContext, + const Signature &origSig, CanSILFunctionType origType, + CanSILFunctionType substType, CanSILFunctionType outType, + SubstitutionMap subs, HeapLayout const *layout, + ArrayRef conventions) + : PartialApplicationForwarderEmission( + IGM, subIGF, fwd, staticFnPtr, calleeHasContext, origSig, origType, + substType, outType, subs, layout, conventions), + Self(nullptr), FirstData(nullptr), SecondData(nullptr) {} + + void begin() override { + auto prototype = subIGF.IGM.getOpaquePtr( + subIGF.IGM.getAddrOfContinuationPrototype(origType)); + + // Use malloc and free as our allocator. + auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn()); + 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::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, 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. + auto hdl = subIGF.Builder.CreateIntrinsicCall( + llvm::Intrinsic::coro_begin, + {id, llvm::ConstantPointerNull::get(subIGF.IGM.Int8PtrTy)}); + + // Set the coroutine handle; this also flags that is a coroutine so that + // e.g. dynamic allocas use the right code generation. + subIGF.setCoroutineHandle(hdl); + + auto *pt = subIGF.Builder.IRBuilderBase::CreateAlloca( + subIGF.IGM.Int1Ty, + /*array size*/ nullptr, "earliest insert point"); + subIGF.setEarliestInsertionPoint(pt); + } + + void gatherArgumentsFromApply() override { + super::gatherArgumentsFromApply(false); + } + llvm::Value *getDynamicFunctionPointer() override { + llvm::Value *Ret = SecondData; + SecondData = nullptr; + return Ret; + } + llvm::Value *getDynamicFunctionContext() override { + llvm::Value *Ret = FirstData; + FirstData = nullptr; + return Ret; + } + void addDynamicFunctionContext(Explosion &explosion) override { + assert(!Self && "context value overrides 'self'"); + FirstData = explosion.claimNext(); + } + void addDynamicFunctionPointer(Explosion &explosion) override { + SecondData = explosion.claimNext(); + } + void addSelf(Explosion &explosion) override { + assert(!FirstData && "'self' overrides another context value"); + if (!hasSelfContextParameter(origType)) { + // witness methods can be declared on types that are not classes. Pass + // such "self" argument as a plain argument. + addArgument(explosion); + return; + } + Self = explosion.claimNext(); + FirstData = Self; + } + + void addWitnessSelfMetadata(llvm::Value *value) override { + Witness.SelfMetadata = value; + } + + void addWitnessSelfWitnessTable(llvm::Value *value) override { + Witness.SelfWitnessTable = value; + } + + void forwardErrorResult() override { + bool isTypedError = origConv.isTypedError(); + SILType origErrorTy = + origConv.getSILErrorType(subIGF.IGM.getMaximalTypeExpansionContext()); + auto errorAlignment = + isTypedError ? subIGF.IGM.getPointerAlignment() + : cast(subIGF.getTypeInfo(origErrorTy)) + .getFixedAlignment(); + auto errorStorageType = + isTypedError ? IGM.Int8PtrTy + : cast(subIGF.getTypeInfo(origErrorTy)) + .getStorageType(); + llvm::Value *errorResultPtr = origParams.claimNext(); + subIGF.setCallerErrorResultSlot( + Address(errorResultPtr, errorStorageType, errorAlignment)); + } + + Explosion callCoroutine(FunctionPointer &fnPtr) { + Callee callee({origType, substType, subs}, fnPtr, FirstData, SecondData); + + std::unique_ptr emitSuspend = + getCallEmission(subIGF, Self, std::move(callee)); + + emitSuspend->begin(); + emitSuspend->setArgs(args, /*isOutlined=*/false, &Witness); + Explosion yieldedValues; + emitSuspend->emitToExplosion(yieldedValues, /*isOutlined=*/false); + emitSuspend->end(); + emitSuspend->claimTemporaries().destroyAll(subIGF); + + if (origConv.getSILResultType(subIGF.IGM.getMaximalTypeExpansionContext()) + .hasTypeParameter()) { + + ArrayRef yieldValues = yieldedValues.claimAll(); + ArrayRef retTypes = + cast(fwd->getReturnType())->elements(); + Explosion yieldCoerced; + assert(yieldValues.size() == retTypes.size() && + "mismatch between return types of the wrapper and the callee"); + for (unsigned i = 0; i < yieldValues.size(); ++i) { + llvm::Value *v = yieldValues[i]; + if (v->getType() != retTypes[i]) { + v = subIGF.coerceValue(v, retTypes[i], subIGF.IGM.DataLayout); + } + yieldCoerced.add(v); + } + return yieldCoerced; + } + + return yieldedValues; + } + + llvm::CallInst *createCall(FunctionPointer &fnPtr) override { + /// Call the wrapped coroutine + /// + Address calleeBuf = emitAllocYieldOnceCoroutineBuffer(subIGF); + llvm::Value *calleeHandle = calleeBuf.getAddress(); + args.insert(0, calleeHandle); + Explosion yieldedValues = callCoroutine(fnPtr); + + /// Get the continuation function pointer + /// + PointerAuthInfo newAuthInfo = + fnPtr.getAuthInfo().getCorrespondingCodeAuthInfo(); + FunctionPointer contFn = FunctionPointer::createSigned( + FunctionPointer::Kind::Function, yieldedValues.claimNext(), newAuthInfo, + Signature::forCoroutineContinuation(subIGF.IGM, origType)); + + /// Forward the remaining yields of the wrapped coroutine + /// + llvm::Value *condUnwind = emitYield(subIGF, substType, yieldedValues); + + llvm::BasicBlock *unwindBB = subIGF.createBasicBlock("unwind"); + llvm::BasicBlock *resumeBB = subIGF.createBasicBlock("resume"); + llvm::BasicBlock *cleanupBB = subIGF.createBasicBlock("cleanup"); + subIGF.CurFn->insert(subIGF.CurFn->end(), unwindBB); + subIGF.CurFn->insert(subIGF.CurFn->end(), resumeBB); + subIGF.CurFn->insert(subIGF.CurFn->end(), cleanupBB); + subIGF.Builder.CreateCondBr(condUnwind, unwindBB, resumeBB); + + /// Call for the results + /// + subIGF.Builder.SetInsertPoint(resumeBB); + + auto isResume = llvm::ConstantInt::get(IGM.Int1Ty, /*isAbort*/ false); + auto *call = subIGF.Builder.CreateCall(contFn, {calleeHandle, isResume}); + + /// Emit coro_end for results and forward them + /// + llvm::Type *callTy = call->getType(); + llvm::Value *noneToken = + llvm::ConstantTokenNone::get(subIGF.Builder.getContext()); + llvm::Value *resultToken = nullptr; + if (callTy->isVoidTy()) { + resultToken = noneToken; + } else if (llvm::StructType *sty = dyn_cast(callTy)) { + Explosion splitCall; + subIGF.emitAllExtractValues(call, sty, splitCall); + resultToken = subIGF.Builder.CreateIntrinsicCall( + llvm::Intrinsic::coro_end_results, splitCall.claimAll()); + } else { + resultToken = subIGF.Builder.CreateIntrinsicCall( + llvm::Intrinsic::coro_end_results, call); + } + + llvm::Value *fwdHandle = subIGF.getCoroutineHandle(); + subIGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_end, + {fwdHandle, isResume, resultToken}); + subIGF.Builder.CreateBr(cleanupBB); + + /// Emit coro_end for unwind + /// + subIGF.Builder.SetInsertPoint(unwindBB); + auto isUnwind = llvm::ConstantInt::get(IGM.Int1Ty, /*isAbort*/ true); + subIGF.Builder.CreateCall(contFn, {calleeHandle, isUnwind}); + subIGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_end, + {fwdHandle, isUnwind, noneToken}); + subIGF.Builder.CreateBr(cleanupBB); + + subIGF.Builder.SetInsertPoint(cleanupBB); + emitDeallocYieldOnceCoroutineBuffer(subIGF, calleeBuf); + llvm::Instruction *cleanupPt = subIGF.Builder.CreateUnreachable(); + subIGF.Builder.SetInsertPoint(cleanupPt); + + return nullptr; + } + + void createReturn(llvm::CallInst *call) override { + // Do nothing, yield/return/unwind blocks are already created in createCall. + } + void end() override { super::end(); } +}; + std::unique_ptr getPartialApplicationForwarderEmission( IRGenModule &IGM, IRGenFunction &subIGF, llvm::Function *fwd, @@ -1434,6 +1676,11 @@ getPartialApplicationForwarderEmission( return std::make_unique( IGM, subIGF, fwd, staticFnPtr, calleeHasContext, origSig, origType, substType, outType, subs, layout, conventions); + } else if (origType->isCoroutine()) { + return std::make_unique( + IGM, subIGF, fwd, staticFnPtr, calleeHasContext, origSig, origType, + substType, outType, subs, layout, conventions); + } else { return std::make_unique( IGM, subIGF, fwd, staticFnPtr, calleeHasContext, origSig, origType, @@ -1611,8 +1858,6 @@ static llvm::Value *emitPartialApplicationForwarder( ti.isSingleSwiftRetainablePointer(ResilienceExpansion::Maximal)) ref = subIGF.coerceValue(rawData, ti.getStorageType(), subIGF.IGM.DataLayout); - else - ref = subIGF.Builder.CreateBitCast(rawData, ti.getStorageType()); param.add(ref); bindPolymorphicParameter(subIGF, origType, substType, param, paramI); (void)param.claimAll(); @@ -1687,7 +1932,7 @@ static llvm::Value *emitPartialApplicationForwarder( auto argIndex = emission->getCurrentArgumentIndex(); if (haveContextArgument) argIndex += polyArgs.size(); - if (origType->isAsync()) + if (origType->isAsync() || origType->isCoroutine()) argIndex += 1; llvm::Type *expectedArgTy = origSig.getType()->getParamType(argIndex); @@ -1712,10 +1957,15 @@ static llvm::Value *emitPartialApplicationForwarder( } else { argValue = subIGF.Builder.CreateBitCast(rawData, expectedArgTy); } - emission->addArgument(argValue); + if (haveContextArgument) { + Explosion e; + e.add(argValue); + emission->addDynamicFunctionContext(e); + } else + emission->addArgument(argValue); - // If there's a data pointer required, grab it and load out the - // extra, previously-curried parameters. + // If there's a data pointer required, grab it and load out the + // extra, previously-curried parameters. } else { unsigned origParamI = outType->getParameters().size(); unsigned extraFieldIndex = 0; @@ -1975,8 +2225,8 @@ static llvm::Value *emitPartialApplicationForwarder( llvm::CallInst *call = emission->createCall(fnPtr); - if (!origType->isAsync() && addressesToDeallocate.empty() && !needsAllocas && - (!consumesContext || !dependsOnContextLifetime)) + if (!origType->isAsync() && !origType->isCoroutine() && addressesToDeallocate.empty() && + !needsAllocas && (!consumesContext || !dependsOnContextLifetime)) call->setTailCall(); // Deallocate everything we allocated above. @@ -2030,7 +2280,7 @@ std::optional irgen::emitFunctionPartialApplication( bool considerParameterSources = true; for (auto param : params) { SILType argType = IGF.IGM.silConv.getSILType( - param, origType, IGF.IGM.getMaximalTypeExpansionContext()); + param, substType, IGF.IGM.getMaximalTypeExpansionContext()); auto argLoweringTy = getArgumentLoweringType(argType.getASTType(), param, outType->isNoEscape()); auto &ti = IGF.getTypeInfoForLowered(argLoweringTy); @@ -2043,7 +2293,7 @@ std::optional irgen::emitFunctionPartialApplication( auto addParam = [&](SILParameterInfo param) { SILType argType = IGF.IGM.silConv.getSILType( - param, origType, IGF.IGM.getMaximalTypeExpansionContext()); + param, substType, IGF.IGM.getMaximalTypeExpansionContext()); auto argLoweringTy = getArgumentLoweringType(argType.getASTType(), param, outType->isNoEscape()); diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 1e9334243eddc..51e30ffbf106e 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -6867,8 +6867,12 @@ void IRGenSILFunction::visitConvertFunctionInst(swift::ConvertFunctionInst *i) { fnType->getRepresentation() != SILFunctionType::Representation::Block) { auto *fn = temp.claimNext(); Explosion res; - auto sig = IGM.getSignature(fnType); - res.add(Builder.CreateBitCast(fn, sig.getType()->getPointerTo())); + auto &fnTI = IGM.getTypeInfoForLowered(fnType); + auto &fnNative = fnTI.nativeReturnValueSchema(IGM); + llvm::Value *newFn = + Builder.CreateBitCast(fn, fnNative.getExpandedType(IGM)); + extractScalarResults(*this, newFn->getType(), newFn, res); + setLoweredExplosion(i, res); return; } diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil new file mode 100644 index 0000000000000..4cb600f088f4e --- /dev/null +++ b/test/IRGen/partial_apply_coro.sil @@ -0,0 +1,1943 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=OnoneSimplification -emit-ir %s -o - | %FileCheck %s --check-prefix=CHECK + +// REQUIRES: concurrency + +import Builtin +import Swift + +// Basic coroutine: a single yield and no results. +// +// CHECK: define {{.*}} { ptr, float } @yield1(ptr noalias dereferenceable(32) %{{.*}}, 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: define {{.*}} void @yield1.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, 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: define {{.*}} void @apply1(float %[[ARG:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata, i32 0, i32 2), i64 20, i64 7) +// 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]], align 8 +// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield1TA"(ptr noalias dereferenceable(32) %[[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-NEXT: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, 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: define {{.*}} { ptr, float } @"$s6yield1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield1(ptr noalias dereferenceable(32) %[[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]], align 8 +// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1 +// CHECK-NEXT: %[[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: define {{.*}} void @"$s6yield1TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-NEXT: entryresume.0: +// CHECK-NEXT: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK-NEXT: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK-NEXT: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK-NEXT: call void @free(ptr %[[FRAME]]) +// CHECK-NEXT: unreachable +// +// CHECK: resume: +// CHECK-NEXT: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK-NEXT: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, float } @yield2(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], float %[[ARG1:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %yield2.Frame, ptr %[[CTX]], i32 0, i32 0 +// CHECK-NEXT: store i64 %[[ARG0]], ptr %[[FRAME]], align 8 +// 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: define {{.*}} i64 @yield2.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-NEXT: entryresume.0: +// CHECK-NEXT: %[[FRAME:.*]] = getelementptr inbounds %yield2.Frame, ptr %[[CTX]], i32 0, i32 0 +// CHECK-NEXT: %[[RET:.*]] = load i64, ptr %[[FRAME]], align 8 +// CHECK-NEXT: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], i64 undef, i64 %[[RET]] +// CHECK-NEXT: ret i64 %[[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: define {{.*}} void @apply2(i64 %[[ARG0:.*]], float %[[ARG1:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 28, i64 7) +// 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-NEXT: store i64 %[[ARG0]], ptr %[[PA_ARG0]], align 8 +// 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]], align 8 +// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield2TA"(ptr noalias dereferenceable(32) %[[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-NEXT: %[[RESULT:.*]] = call swiftcc i64 %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, 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: define {{.*}} { ptr, float } @"$s6yield2TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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 i64, ptr %[[ARG0PTR]], align 8 +// 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]], align 8 +// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield2(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[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]], align 8 +// CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1 +// CHECK-NEXT: %[[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: define {{.*}} i64 @"$s6yield2TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-NEXT: entryresume.0: +// CHECK-NEXT: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK-NEXT: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK-NEXT: %{{.*}} = call swiftcc i64 %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK-NEXT: call void @free(ptr %[[FRAME]]) +// CHECK-NEXT: unreachable +// +// CHECK: resume: +// CHECK-NEXT: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK-NEXT: %[[RET:.*]] = call swiftcc i64 %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// CHECK-NEXT: call void @free(ptr %[[FRAME]]) +// CHECK-NEXT: ret i64 %[[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: define {{.*}} { ptr, ptr } @yieldgen1(ptr noalias dereferenceable(32) %{{.*}}, ptr noalias %[[ARG1:.*]], ptr %[[ARG2:.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: %[[SPILL_ARG2:.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr %[[ARG2]], ptr %[[SPILL_ARG2]], align 8 +// 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: define {{.*}} void @yieldgen1.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, i1 %[[UNWIND:.*]]) +// CHECK-NEXT: entryresume.0: +// CHECK-NEXT: %T1 = alloca ptr +// CHECK-NEXT: ret void +// CHECK-NEXT: } +// +sil @yieldgen1 : $@yield_once @convention(thin) (@in T) -> (@yields @in T) { +bb0(%t : $*T): + yield (%t : $*T), resume bb1, unwind bb2 + +bb1: + %r = tuple () + return %r : $() + +bb2: + unwind +} + +// CHECK: define {{.*}} void @applygen1(float %[[ARG:.*]]) +// CHECK-NEXT: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen1TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[ARGBOXED:.*]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 +// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: call void @swift_release(ptr %[[ARGBOXED]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s9yieldgen1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 48) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen1(ptr noalias dereferenceable(32) %[[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, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// 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: define {{.*}} void @"$s9yieldgen1TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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) (@in T) -> (@yields @in T) + %temp = alloc_stack $Float + store %0 to [trivial] %temp : $*Float + %pa = partial_apply [callee_guaranteed] %coro(%temp) : $@yield_once @convention(thin) (@in T) -> (@yields @in T) + + (%value, %token) = begin_apply %pa() : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T) for + + end_apply %token as $() + destroy_value %pa : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T) for + + dealloc_stack %temp : $*Float + %r = tuple () + return %r : $() +} + +// FIXME: Support coroutine indirect results +// sil @yieldgen2 : $@yield_once @convention(thin) (@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 +// } + +// sil [ossa] @applygen2 : $(Float) -> () { +// bb0(%0 : $Float): +// %coro = function_ref @yieldgen2 : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) +// %temp = alloc_stack $Float +// store %0 to [trivial] %temp : $*Float +// %pa = partial_apply [callee_guaranteed] %coro(%temp) : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) +// +// %out = alloc_stack $Float +// (%f1, %token) = begin_apply %pa(%out) : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for +// +// %f2 = end_apply %token as $() +// destroy_value %pa : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for +// +// 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: define {{.*}} { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(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: define {{.*}} void @partially_applyable_to_class.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, 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: define {{.*}} { ptr, ptr } @partial_apply_class(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: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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: define {{.*}} void @"$s28partially_applyable_to_classTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} void @partial_apply_class_on_stack(ptr %[[ARG:.*]]) +// CHECK: entry: +// CHECK: call swiftcc void @use_closure(ptr @"$s28partially_applyable_to_classTA.7", ptr %[[ARG]]) +// CHECK: call void @swift_release(ptr %[[ARG]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.7"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s28partially_applyable_to_classTA.7.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1 +// CHECK: ret { ptr, ptr } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s28partially_applyable_to_classTA.7.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, ptr } @partially_applyable_to_two_classes(ptr noalias dereferenceable(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]], align 8 +// 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: define {{.*}} ptr @partially_applyable_to_two_classes.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[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]], align 8 +// 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: define {{.*}} void @partial_apply_two_classes_on_stack(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = alloca i8, i64 32, align 16 +// CHECK: %[[BOXPTR0:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr, ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR0]], align 8 +// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr, ptr }>, ptr %[[BOX]], i32 0, i32 2 +// CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]], align 8 +// 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: define {{.*}} { ptr, ptr } @"$s34partially_applyable_to_two_classesTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[PA_CTX1:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX1]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_two_classes(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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: define {{.*}} ptr @"$s34partially_applyable_to_two_classesTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @generic_captured_param(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr %[[ARG1:.*]], ptr %[[ARG2:.*]]) +// CHECK: entry: +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @generic_captured_param.resume.0, 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[ARG0]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @generic_captured_param.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: ret void +// CHECK: } +// +sil @generic_captured_param : $@yield_once @convention(thin) (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: define {{.*}} { ptr, ptr } @partial_apply_generic_capture(i64 %[[ARG0:.*]]) +// CHECK: entry: +// CHECK: %[[ARG:.*]] = alloca %TSi, align 8 +// CHECK: call void @llvm.lifetime.start.p0(i64 8, ptr %[[ARG]]) +// CHECK: %[[ARGPTR:.*]] = getelementptr inbounds %TSi, ptr %[[ARG]], i32 0, i32 0 +// CHECK: store i64 %[[ARG0]], ptr %[[ARGPTR]], align 8 +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 24, i64 7) +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 +// CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[ARG]]) +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s22generic_captured_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s22generic_captured_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @generic_captured_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr %[[ARG1]], ptr @"$sSiN") +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s22generic_captured_paramTA.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s22generic_captured_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s22generic_captured_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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) (Int, @inout T) -> (@yields Int) + %p = partial_apply [callee_guaranteed] %f(%a) : $@yield_once @convention(thin) (Int, @inout T) -> (@yields Int) + dealloc_stack %a : $*Int + return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int) +} + +// CHECK: define {{.*}} { ptr, ptr } @generic_captured_and_open_param(ptr noalias dereferenceable(32) %0, ptr noalias %1, ptr %2, ptr %T) +sil public @generic_captured_and_open_param : $@yield_once @convention(thin) (@in T, @inout T) -> (@yields @in T) { +entry(%i : $*T, %io : $*T): + %0 = builtin "int_trap"() : $Never + unreachable +} + +// CHECK: define{{.*}} swiftcc { ptr, ptr } @partial_apply_open_generic_capture(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]], align 8 +// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 +// CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR2]], align 8 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31generic_captured_and_open_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define internal swiftcc { ptr, ptr } @"$s31generic_captured_and_open_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr noalias %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX]], align 8 +// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// CHECK: %[[ARG2:.*]] = load ptr, ptr %[[PA_CTX2]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @generic_captured_and_open_param(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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: define internal swiftcc void @"$s31generic_captured_and_open_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: ret void +// CHECK: } +// +sil @partial_apply_open_generic_capture : $@convention(thin) (@inout T) -> @yield_once @callee_guaranteed @substituted (@in T) -> @yields @in T for { +entry(%a : $*T): + %f = function_ref @generic_captured_and_open_param : $@yield_once @convention(thin) (@in U, @inout U) -> (@yields @in U) + %p = partial_apply [callee_guaranteed] %f(%a) : $@yield_once @convention(thin) (@in U, @inout U) -> (@yields @in U) + return %p : $@yield_once @callee_guaranteed @substituted (@in T) -> @yields @in T for +} + +/*****************************************************************************/ +/* Swift-refcounted class captures. Optimizable by using the reference */ +/* as the partial apply context. */ +/*****************************************************************************/ + +// CHECK: define {{.*}} { ptr, ptr } @guaranteed_captured_class_param(ptr noalias dereferenceable(32) %0, 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: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_param(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: define {{.*}} { ptr, ptr } @"$s31guaranteed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @guaranteed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[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]], align 8 +// 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: define {{.*}} void @"$s31guaranteed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, ptr } @indirect_guaranteed_captured_class_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(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: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) +// CHECK: entry: +// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s40indirect_guaranteed_captured_class_paramTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s40indirect_guaranteed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: store ptr %[[PA_CTX_BOX]], ptr %[[SELFPTR]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_guaranteed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(8) %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 +// CHECK: %9 = insertvalue { ptr, ptr } poison, ptr @"$s40indirect_guaranteed_captured_class_paramTA.resume.0", 0 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } %9, ptr %[[YIELD]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s40indirect_guaranteed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, ptr } @indirect_consumed_captured_class_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(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: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) +// CHECK: entry: +// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s38indirect_consumed_captured_class_paramTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s38indirect_consumed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_consumed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(8) %[[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]], align 8 +// 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: define {{.*}} void @"$s38indirect_consumed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, 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: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_pair_param(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// 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]], align 8 +// CHECK: %[[ARG1PTR:.*]] = getelementptr inbounds %T18partial_apply_coro14SwiftClassPairV, ptr %[[BOXPTR]], i32 0, i32 1 +// CHECK: store ptr %[[ARG1]], ptr %[[ARG1PTR]], align 8 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s36guaranteed_captured_class_pair_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s36guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[PA_CTX_ARG2:.*]] = getelementptr inbounds %T18partial_apply_coro14SwiftClassPairV, ptr %[[PA_CTX]], i32 0, i32 1 +// CHECK: %[[ARG2:.*]] = load ptr, ptr %[[PA_CTX_ARG2]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr %[[ARG1]], ptr %[[ARG2]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s36guaranteed_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s36guaranteed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(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: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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 [32 x i8], ptr %[[SPILL1]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %1, ptr noalias nocapture dereferenceable(16) %[[PA_CTX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %10 = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %11 = insertvalue { ptr, i64 } %10, i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %11 +// CHECK: } +// +// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(16) %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: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, 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: define {{.*}} { ptr, i64 } @"$s43indirect_consumed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 56) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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 16, ptr %[[SPILL1]]) +// CHECK: %{{.*}} = call ptr @"$s18partial_apply_coro14SwiftClassPairVWOc"(ptr %[[PA_CTX]], ptr %[[SPILL1]]) +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %1, ptr noalias nocapture dereferenceable(16) %[[SPILL1]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[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: define {{.*}} ptr @captured_fixed_and_dependent_params(ptr noalias dereferenceable(32) %0, ptr %1, ptr noalias %2, i64 %3, ptr %A) +sil public @captured_fixed_and_dependent_params : $@yield_once @convention(thin) (@guaranteed SwiftClass, @in_guaranteed A, Int) -> () { +entry(%c : $SwiftClass, %a : $*A, %i : $Int): + %0 = builtin "int_trap"() : $Never + unreachable +} + +// CHECK: define{{.*}} swiftcc { ptr, ptr } @partial_apply_indirect_non_fixed_layout(ptr %[[CTX:.*]], ptr noalias %[[ARG0:.*]], i64 %[[ARG1:.*]], ptr %[[TY:.*]]) +// CHECK: entry: +// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], i64 -1 +// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// CHECK: %[[WITNESS:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 10 +// CHECK: %[[FLAGS:.*]] = load i32, ptr %[[WITNESS]], align 8 +// do not check computation of align; may be target dependent +// CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8 +// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]], align 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{{.*}}, i32 0, i32 2), i64 %{{.*}}, i64 %{{.*}}) +// CHECK: %[[BOXPTR0:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[TY]], ptr %[[BOXPTR0]], align 8 +// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 +// CHECK: store ptr %[[CTX]], ptr %[[BOXPTR1]], align 8 +// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds i8, ptr %[[BOX]], i64 %8 +// CHECK: %[[INITPTR:.*]] = getelementptr inbounds ptr, ptr %[[VWTABLE]], i32 4 +// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INITPTR]], align 8 +// CHECK: %{{.*}} = call ptr %[[INIT]](ptr noalias %[[BOXPTR2]], ptr noalias %[[ARG0]], ptr %[[TY]]) +// CHECK: %[[BOXPTR3:.*]] = getelementptr inbounds i8, ptr %[[BOX]], i64 %{{.*}} +// CHECK: %[[BOXPTR3VAL:.*]] = getelementptr inbounds %TSi, ptr %[[BOXPTR3]], i32 0, i32 0 +// CHECK: store i64 %[[ARG1]], ptr %[[BOXPTR3VAL]], align 8 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s35captured_fixed_and_dependent_paramsTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define internal swiftcc ptr @"$s35captured_fixed_and_dependent_paramsTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[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]], align 8 +// CHECK: store ptr %[[TY]], ptr %[[TY]]1, align 8 +// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], i64 -1 +// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// CHECK: %[[WITNESS:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 10 +// CHECK: %[[FLAGS:.*]] = load i32, ptr %[[WITNESS]], align 8 +// do not check computation of align; may be target dependent +// CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8 +// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]], align 8 +// do not check computation of size; may be target dependent +// CHECK: %[[PA_CTX2:.8]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// CHECK: %[[ARG0:.*]] = load ptr, ptr %[[PA_CTX2]], align 8 +// CHECK: %[[ARG1:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} +// CHECK: %[[ARG2PTR0:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} +// CHECK: %[[ARG2PTR1:.*]] = getelementptr inbounds %TSi, ptr %[[ARG2PTR0]], i32 0, i32 0 +// CHECK: %[[ARG2:.*]] = load i64, ptr %[[ARG2PTR1]], align 8 +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[RESUME:.*]] = call swiftcc ptr @captured_fixed_and_dependent_params(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[ARG0]], ptr noalias %[[ARG1]], i64 %[[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]], align 8 +// CHECK: ret ptr @"$s35captured_fixed_and_dependent_paramsTA.resume.0" +// CHECK: } +// +// CHECK: define internal swiftcc void @"$s35captured_fixed_and_dependent_paramsTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: ret void +// CHECK: } +// +sil @partial_apply_indirect_non_fixed_layout : $@convention(thin) (@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) (@guaranteed SwiftClass, @in_guaranteed B, Int) -> () + %p = partial_apply [callee_guaranteed] %f(%a, %b, %c) : $@yield_once @convention(thin) (@guaranteed SwiftClass, @in_guaranteed C, Int) -> () + return %p : $@yield_once @callee_guaranteed () -> () +} + +// FIXME: Support coroutine indirect results +// sil public @captured_dependent_out_param : $@yield_once @convention(thin) (@in A) -> (@out A, @yields A) { +// entry(%o : $*A, %i : $*A): +// %0 = builtin "int_trap"() : $Never +// unreachable +// } + +// sil @partial_apply_with_out_param : $@convention(thin) (@in T) -> @yield_once @callee_guaranteed () -> (@out T, @yields T) { +// bb0(%x : $*T): +// %f = function_ref @captured_dependent_out_param : $@yield_once @convention(thin) (@in B) -> (@out B, @yields B) +// %p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (@in C) -> (@out C, @yields C) +// return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields T) +// } + +// sil @partial_apply_dynamic_with_out_param : $@convention(thin) (Int32, @owned @yield_once @callee_guaranteed (Int32) -> (@out T, @yields T)) -> @yield_once @callee_guaranteed () -> (@out T, @yields T) { +// bb0(%x : $Int32, %f : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields T)): +// %p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields T) +// return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields T) +// } + +class Base { +} + +sil_vtable Base {} + +class Sub : Base { +} + +sil_vtable Sub {} + +sil public_external @receive_closure : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> () +sil public_external @receive_closure2 : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> () + +// CHECK: define {{.*}} { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(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]], align 8 +// 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: define {{.*}} ptr @parametric_casting_closure.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[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]], align 8 +// CHECK: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], ptr undef, ptr %[[RET]] +// CHECK: ret ptr %[[RET_SEL]] +// CHECK: } +// +sil @parametric_casting_closure : $@yield_once @convention(thin) (@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: define{{.*}} swiftcc void @test_partial_apply(ptr %[[ARG0:.*]]) +// CHECK: entry: +// CHECK: %[[CTX0:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[CTX1:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[CTX0PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX0]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX0PTR]]) +// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) +// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 +// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.26", ptr %[[ARG0]], ptr %[[MD]]) +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0PTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX0PTR]]) +// CHECK: %[[CTX1PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX1]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX1PTR]]) +// CHECK: %[[RESUME1:.*]] = call swiftcc ptr @receive_closure2(ptr noalias dereferenceable(32) %[[CTX1PTR]], ptr @"$s26parametric_casting_closureTA", ptr null, ptr %[[MD]]) +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1PTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX1PTR]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) +// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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: define {{.*}} ptr @"$s26parametric_casting_closureTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: ret ptr %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.26"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) +// CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]], ptr %[[MD]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s26parametric_casting_closureTA.26.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, ptr } %[[RET0]], ptr %[[YIELD]], 1 +// CHECK: ret { ptr, ptr } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} ptr @"$s26parametric_casting_closureTA.26.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[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) (@guaranteed Base) -> (@owned C, @yields C) + %6 = partial_apply [callee_guaranteed] %1() : $@yield_once @convention(thin) (@guaranteed Base) -> (@owned C, @yields C) + %2 = partial_apply [callee_guaranteed] %1(%0) : $@yield_once @convention(thin) (@guaranteed Base) -> (@owned C, @yields C) + %3 = function_ref @receive_closure : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> () + %2c = convert_function %2: $@yield_once @callee_guaranteed @substituted () -> (@owned C, @yields C) for to $@yield_once @callee_guaranteed () -> (@owned Sub, @yields Sub) + %t1 = begin_apply %3(%2c) : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> () + end_apply %t1 as $() + + %5 = function_ref @receive_closure2 : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> () + %6c = convert_function %6: $@yield_once @callee_guaranteed @substituted (@guaranteed Base) -> (@owned C, @yields C) for to $@yield_once @callee_guaranteed (@guaranteed Base) -> (@owned Sub, @yields Sub) + %t2 = begin_apply %5(%6c) : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> () + end_apply %t2 as $() + + %7 = tuple () + return %7 : $() +} + +// Crash on partial apply of a generic enum. +enum GenericEnum { + case X(String) + case Y(T, T, T, T, T) +} + +// FIXME: Support coroutine indirect results + +// sil public @generic_indirect_return : $@yield_once @convention(thin) (Int) -> @owned GenericEnum { +// entry(%i : $Int): +// %0 = builtin "int_trap"() : $Never +// unreachable +// } + +// sil @partial_apply_generic_indirect_return : $@convention(thin) (Int) -> @yield_once @callee_guaranteed () -> @owned GenericEnum { +// bb0(%0 : $Int): +// %fn = function_ref @generic_indirect_return :$@yield_once @convention(thin) (Int) -> @owned GenericEnum +// %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum +// return %pa : $@yield_once @callee_guaranteed () -> @owned GenericEnum +// } + +// sil public @generic_indirect_return2 : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 { +// entry(%i : $Int): +// %0 = builtin "int_trap"() : $Never +// unreachable +// } + +// sil @partial_apply_generic_indirect_return2 : $@convention(thin) (Int) -> @yield_once @callee_guaranteed @substituted () -> @owned GenericEnum2 for { +// bb0(%0 : $Int): +// %fn = function_ref @generic_indirect_return2 :$@yield_once @convention(thin) (Int) -> @owned GenericEnum2 +// %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 +// return %pa : $@yield_once @callee_guaranteed @substituted () -> @owned GenericEnum2 for +// } + +struct SwiftStruct {} + +// CHECK: define {{.*}} { ptr, ptr } @fun(ptr noalias dereferenceable(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: define{{.*}} swiftcc { ptr, ptr } @partial_apply_thin_type(ptr %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s3funTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr } @"$s3funTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @fun(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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: define {{.*}} void @"$s3funTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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 { + let a: T +} + +class A3 {} + +sil_vtable A3 {} + +// CHECK: define {{.*}} { ptr, ptr, ptr } @amethod(ptr noalias dereferenceable(32) %0, ptr noalias nocapture swiftself dereferenceable(8) %1, ptr noalias nocapture swifterror dereferenceable(8) %2) +sil @amethod : $@yield_once @convention(method) (@in_guaranteed A2) -> (@yields A1, @error Error) { +entry(%a : $*A2): + %0 = builtin "int_trap"() : $Never + unreachable +} + +// CHECK: define {{.*}} { ptr, ptr } @repo(ptr noalias nocapture dereferenceable(8) %[[ARG:.*]]) +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s7amethodTA", ptr undef }, ptr %{{.*}}, 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, ptr, ptr } @"$s7amethodTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[SELF:.*]], ptr noalias nocapture swifterror dereferenceable(8) %[[ERRORPTR:.*]]) +// CHECK: entry: +// CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: store ptr %[[SELF]], ptr %[[SELFPTR]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: store ptr null, ptr %[[ERRORPTR]], align 8 +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr, ptr } @amethod(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr noalias nocapture swiftself dereferenceable(8) %[[SELFPTR]], ptr noalias nocapture swifterror dereferenceable(8) %[[ERRORPTR]]) +// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]], align 8 +// 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]], align 8 +// CHECK: %[[YIELD0:.*]] = extractvalue { ptr, ptr, ptr } %[[YIELD_PAIR]], 1 +// CHECK: %[[YIELD1:.*]] = extractvalue { ptr, ptr, ptr } %[[YIELD_PAIR]], 2 +// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]], align 8 +// 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: define {{.*}} void @"$s7amethodTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[ERRORPTR:.*]] = alloca swifterror ptr, align 8 +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]], align 8 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]], align 8 +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]], align 8 +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: ret void +// CHECK: } +// +sil @repo : $@convention(thin) (@in_guaranteed A2) -> @owned @yield_once @callee_guaranteed () -> (@yields A1, @error Error) { +bb0(%0 : $*A2): + %1 = load %0 : $*A2 + %2 = alloc_stack $A2 + store %1 to %2 : $*A2 + %4 = function_ref @amethod : $@yield_once @convention(method) (@in_guaranteed A2) -> (@yields A1, @error Error) + %5 = partial_apply [callee_guaranteed] %4(%2) : $@yield_once @convention(method) (@in_guaranteed A2) -> (@yields A1, @error Error) + dealloc_stack %2 : $*A2 + return %5 : $@yield_once @callee_guaranteed () -> (@yields A1, @error Error) +} + +// CHECK: define {{.*}} { ptr, ptr } @partial_apply_callee_guaranteed_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.30", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.30"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[PA_ARG]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[PA_ARG]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_CTX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.30.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.30.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} @partial_apply_stack_callee_guaranteed_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.31", ptr %[[BOX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.31"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.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]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.31.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.31.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @indirect_in_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %{{.*}}, ptr noalias nocapture dereferenceable(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: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s37indirect_in_captured_class_pair_paramTA", ptr %[[BOX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %8 = call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s37indirect_in_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_in_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s37indirect_in_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s37indirect_in_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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: define {{.*}} { ptr, i64 } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(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: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_constant_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s46indirect_in_constant_captured_class_pair_paramTA", ptr %[[BOX]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]]) +// CHECK: ret void +// CHECK: } +// +// CHECK: define {{.*}} { ptr, i64 } @"$s46indirect_in_constant_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) +// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[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]], align 8 +// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET1]] +// CHECK: } +// +// CHECK: define {{.*}} void @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: 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]], align 8 +// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: 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]], align 8 +// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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 +} + +// 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) +// } + +sil @method_with_out_return : $@convention(method) @yield_once (SwiftClass) -> @out Int + +// FIXME: Support coroutine indirect results +// 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 +// } From d34bb4b3f732ccec978f1b59b350b3a4d05f32cf Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Mon, 19 Feb 2024 17:33:14 +0900 Subject: [PATCH 02/12] Handle begin_apply in PartialApplyCombiner --- .../Utils/PartialApplyCombiner.cpp | 4 +++ test/SILOptimizer/sil_combine_apply_ossa.sil | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp index 43726cb0414d3..1b2e8a10c5e0c 100644 --- a/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp +++ b/lib/SILOptimizer/Utils/PartialApplyCombiner.cpp @@ -207,6 +207,10 @@ void PartialApplyCombiner::processSingleApply(FullApplySite paiAI) { builder.createTryApply(paiAI.getLoc(), callee, subs, argList, tai->getNormalBB(), tai->getErrorBB(), tai->getApplyOptions()); + } else if (auto *bai = dyn_cast(paiAI)) { + auto *newBAI = builder.createBeginApply(paiAI.getLoc(), callee, subs, + argList, bai->getApplyOptions()); + callbacks.replaceAllInstUsesPairwiseWith(bai, newBAI); } else { auto *apply = cast(paiAI); auto *newAI = builder.createApply(paiAI.getLoc(), callee, subs, argList, diff --git a/test/SILOptimizer/sil_combine_apply_ossa.sil b/test/SILOptimizer/sil_combine_apply_ossa.sil index b59aa82da515f..3711f6748cd47 100644 --- a/test/SILOptimizer/sil_combine_apply_ossa.sil +++ b/test/SILOptimizer/sil_combine_apply_ossa.sil @@ -1175,3 +1175,33 @@ bb0(%0 : $Int): sil [ossa] @closure2 : $@convention(thin) (Int) -> () +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 +} + +// CHECK-LABEL: sil [ossa] @coro_apply1 +// CHECK: %[[REF:.*]] = function_ref @yield1 : $@yield_once @convention(thin) (Float) -> @yields Float +// CHECK: (%{{.*}}, %[[CONT:.*]]) = begin_apply %[[REF]](%{{.*}}) : $@yield_once @convention(thin) (Float) -> @yields Float +// CHECK: %{{.*}} = end_apply %[[CONT]] as $() +// CHECK-LABEL: } // end sil function 'coro_apply1' +sil [ossa] @coro_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 : $() +} From e1dc1b65078f7243c1a8964b681d98b6cd4dca2c Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 22 May 2024 18:08:24 -0700 Subject: [PATCH 03/12] Add autodiff execution test for modify accessor differentiation --- .../validation-test/modify_accessor.swift | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 test/AutoDiff/validation-test/modify_accessor.swift diff --git a/test/AutoDiff/validation-test/modify_accessor.swift b/test/AutoDiff/validation-test/modify_accessor.swift new file mode 100644 index 0000000000000..dc7576f2770f3 --- /dev/null +++ b/test/AutoDiff/validation-test/modify_accessor.swift @@ -0,0 +1,43 @@ +// RUN: %target-run-simple-swift +// REQUIRES: executable_test + +import _Differentiation +import StdlibUnittest + +var ModifyAccessorTests = TestSuite("ModifyAccessor") + +ModifyAccessorTests.test("SimpleModifyAccessor") { + struct S: Differentiable { + private var _x : Float + + func _endMutation() {} + + var x: Float { + get{_x} + set(newValue) { _x = newValue } + _modify { + defer { _endMutation() } + if (x > 0) { + yield &_x + } else { + yield &_x + } + } + } + + init(_ x : Float) { + self._x = x + } + } + + func modify_struct(_ x : Float) -> Float { + var s = S(x) + s.x *= s.x + return s.x + } + + expectEqual((100, 20), valueWithGradient(at: 10, of: modify_struct)) +} + +runAllTests() + From 01a2a4a23ecf120455f85a9887b6fe99d6f24436 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Mon, 15 Jul 2024 16:08:58 +0900 Subject: [PATCH 04/12] Add remaining partial_apply.sil tests for partial_apply_coro.sil --- test/IRGen/partial_apply_coro.sil | 537 +++++++++++++++++++++++------- 1 file changed, 421 insertions(+), 116 deletions(-) diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index 4cb600f088f4e..151aa8df7880d 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -332,39 +332,135 @@ bb0(%0 : $Float): return %r : $() } -// FIXME: Support coroutine indirect results -// sil @yieldgen2 : $@yield_once @convention(thin) (@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 -// } +// Coroutine with a generic yield and a generic indirect result +// +// CHECK: define {{.*}} { ptr, ptr } @yieldgen2(ptr noalias dereferenceable(32) %[[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]], align 8 +// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1 +// CHECK: store ptr %[[ARG]], ptr %[[SPILL1]], align 8 +// CHECK: %[[SPILL0:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 0 +// CHECK: store ptr %[[INDIRECT_RET]], ptr %[[SPILL0]], align 8 +// 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: define {{.*}} void @yieldgen2.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 2 +// CHECK: %[[TYPE:.*]] = load ptr, ptr %[[SPILL2]], align 8 +// CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1 +// CHECK: %[[ARG:.*]] = load ptr, ptr %[[SPILL1]], align 8 +// CHECK: %[[SPILL0:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 0 +// CHECK: %[[INDIRECT_RET:.*]] = load ptr, ptr %[[SPILL0]], align 8 +// CHECK: %[[VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[TYPE]], i64 -1 +// CHECK: %[[VW:.*]] = load ptr, ptr %[[VW_PTR]], align 8 +// CHECK: %[[ASSIGN_PTR:.*]] = getelementptr inbounds ptr, ptr %[[VW]], i32 3 +// CHECK: %[[ASSIGN:.*]] = load ptr, ptr %[[ASSIGN_PTR]], align 8 +// CHECK: call ptr %[[ASSIGN]](ptr %[[INDIRECT_RET]], ptr %[[ARG]], ptr %[[TYPE]]) +// +sil @yieldgen2 : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) { +bb0(%outt : $*T, %t : $*T): + yield (%t : $*T), resume bb1, unwind bb2 -// sil [ossa] @applygen2 : $(Float) -> () { -// bb0(%0 : $Float): -// %coro = function_ref @yieldgen2 : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) -// %temp = alloc_stack $Float -// store %0 to [trivial] %temp : $*Float -// %pa = partial_apply [callee_guaranteed] %coro(%temp) : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) -// -// %out = alloc_stack $Float -// (%f1, %token) = begin_apply %pa(%out) : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for -// -// %f2 = end_apply %token as $() -// destroy_value %pa : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for -// -// dealloc_stack %out : $*Float -// dealloc_stack %temp : $*Float -// -// %r = tuple () -// return %r : $() -// } +bb1: + copy_addr %t to %outt : $*T + %r = tuple () + return %r : $() + +bb2: + unwind +} + +// CHECK: define {{.*}} void @applygen2(float %[[ARG:.*]]) +// CHECK-NEXT: entry: +// CHECK: %[[ARG_COPY:.*]] = alloca %TSf, align 4 +// CHECK: %[[INDIRECT_RET:.*]] = alloca %TSf, align 4 +// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// 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: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[PA_CTX_ARG]], ptr align 4 %[[ARG_COPY]], i64 4, i1 false) +// CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %[[INDIRECT_RET]]) +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen2TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[INDIRECT_RET]], 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 dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]]) +// 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: define internal swiftcc { ptr, ptr } @"$s9yieldgen2TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_BOX_CTX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 48) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[SPILL]], i32 0, i32 2 +// 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: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[SPILL2:.*]], ptr align 8 %[[ARG]], i64 4, i1 false) +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen2(ptr noalias dereferenceable(32) %[[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, i32 1 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]], align 8 +// 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: define {{.*}} void @"$s9yieldgen2TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: entryresume.0: +// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 2 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 0 +// CHECK: br i1 %[[UNWIND]], label %unwind, label %resume +// +// CHECK: unwind: +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0:.*]], align 8 +// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX]], i1 true) +// CHECK: call void @free(ptr %[[FRAME]]) +// CHECK: unreachable +// +// CHECK: resume: +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 +// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 +// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[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) (@in T) -> (@yields @in T, @out T) + %temp = alloc_stack $Float + store %0 to [trivial] %temp : $*Float + %pa = partial_apply [callee_guaranteed] %coro(%temp) : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) + + %out = alloc_stack $Float + (%f1, %token) = begin_apply %pa(%out) : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for + + %f2 = end_apply %token as $() + destroy_value %pa : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T, @out T) for + + 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. @@ -454,36 +550,36 @@ sil @use_closure_two : $@convention(thin) (@noescape @yield_once @callee_guarant // CHECK: define {{.*}} void @partial_apply_class_on_stack(ptr %[[ARG:.*]]) // CHECK: entry: -// CHECK: call swiftcc void @use_closure(ptr @"$s28partially_applyable_to_classTA.7", ptr %[[ARG]]) +// 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: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.7"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 -// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) // CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s28partially_applyable_to_classTA.7.resume.0", 0 +// 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: define {{.*}} void @"$s28partially_applyable_to_classTA.7.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: define {{.*}} void @"$s28partially_applyable_to_classTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 0 +// 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: unwind: -// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -491,7 +587,7 @@ sil @use_closure_two : $@convention(thin) (@noescape @yield_once @callee_guarant // CHECK: unreachable // // CHECK: resume: -// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.7.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -1262,24 +1358,82 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): return %p : $@yield_once @callee_guaranteed () -> () } -// FIXME: Support coroutine indirect results -// sil public @captured_dependent_out_param : $@yield_once @convention(thin) (@in A) -> (@out A, @yields A) { -// entry(%o : $*A, %i : $*A): -// %0 = builtin "int_trap"() : $Never -// unreachable -// } +// CHECK: @partial_apply_with_out_param +// CHECK-SAME: (ptr noalias %[[ARG:.*]], ptr %[[ARGTY:.*]]) +// CHECK: entry: +// CHECK: %[[ARGTY_VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[ARGTY]], i64 -1 +// CHECK: %[[ARGTY_VW:.*]] = load ptr, ptr %[[ARGTY_VW_PTR]] +// CHECK: %[[ARGTY_FLAGS_PTR:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[ARGTY_VW]], i32 0, i32 10 +// CHECK: %[[ARGTY_FLAGS_I32:.*]] = load i32, ptr %[[ARGTY_FLAGS_PTR]] +// CHECK: %[[ARGTY_FLAGS:.*]] = zext i32 %[[ARGTY_FLAGS_I32]] to i64 +// CHECK: %[[ARGTY_ALIGN1:.*]] = and i64 %[[ARGTY_FLAGS]], 255 +// CHECK: %[[ARGTY_ALIGN2:.*]] = xor i64 %[[ARGTY_ALIGN1]], -1 +// CHECK: %[[ARGTY_ALIGN3:.*]] = add i64 24, %[[ARGTY_ALIGN1]] +// CHECK: %[[ARGTY_ALIGN4:.*]] = and i64 %[[ARGTY_ALIGN3]], %[[ARGTY_ALIGN2]] +// CHECK: %[[ARGTY_SIZE_PTR:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[ARGTY_VW]], i32 0, i32 8 +// CHECK: %[[ARGTY_SIZE1:.*]] = load i64, ptr %[[ARGTY_SIZE_PTR]] +// CHECK: %[[ARGTY_SIZE2:.*]] = add i64 %[[ARGTY_ALIGN4]], %[[ARGTY_SIZE1]] +// CHECK: %[[ARGTY_ALIGN5:.*]] = or i64 7, %[[ARGTY_ALIGN1]] +// CHECK: %[[PA_BOX_ALLOC:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @{{.*}}, i32 0, i32 2), i64 %[[ARGTY_SIZE2]], i64 %[[ARGTY_ALIGN5]]) +// CHECK: %[[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]], i64 %[[ARGTY_ALIGN4]] +// CHECK: %[[INIT_PTR:.*]] = getelementptr inbounds ptr, ptr %[[ARGTY_VW]], i32 4 +// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INIT_PTR]], align 8, !invariant.load !7 +// 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: 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(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28captured_dependent_out_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[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]], i64 -1 +// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]] +// 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 +// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]] +// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} +// CHECK: %[[ARG_COPY:.*]] = call ptr @malloc(i64 %[[SIZE]]) +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @captured_dependent_out_param(ptr noalias dereferenceable(32) %[[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]], align 8 +// 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 @partial_apply_with_out_param : $@convention(thin) (@in T) -> @yield_once @callee_guaranteed () -> (@out T, @yields T) { -// bb0(%x : $*T): -// %f = function_ref @captured_dependent_out_param : $@yield_once @convention(thin) (@in B) -> (@out B, @yields B) -// %p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (@in C) -> (@out C, @yields C) -// return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields T) -// } +sil public @captured_dependent_out_param : $@yield_once @convention(thin) (@in A) -> (@out A, @yields @in A) { +entry(%o : $*A, %i : $*A): + %0 = builtin "int_trap"() : $Never + unreachable +} -// sil @partial_apply_dynamic_with_out_param : $@convention(thin) (Int32, @owned @yield_once @callee_guaranteed (Int32) -> (@out T, @yields T)) -> @yield_once @callee_guaranteed () -> (@out T, @yields T) { -// bb0(%x : $Int32, %f : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields T)): -// %p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @callee_guaranteed (Int32) -> (@out T, @yields T) -// return %p : $@yield_once @callee_guaranteed () -> (@out T, @yields T) +sil @partial_apply_with_out_param : $@convention(thin) (@in T) -> @yield_once @callee_guaranteed @substituted () -> (@out T, @yields @in T) for { +bb0(%x : $*T): + %f = function_ref @captured_dependent_out_param : $@yield_once @convention(thin) (@in B) -> (@out B, @yields @in B) + %p = partial_apply [callee_guaranteed] %f(%x) : $@yield_once @convention(thin) (@in C) -> (@out C, @yields @in C) + return %p : $@yield_once @callee_guaranteed @substituted () -> (@out T, @yields @in T) for +} + +// FIXME: Cannot mangle free-standing archetypes +// sil @partial_apply_dynamic_with_out_param : $@convention(thin) (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) // } class Base { @@ -1333,7 +1487,7 @@ bb2: // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX0PTR]]) // CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) // CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 -// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.26", ptr %[[ARG0]], ptr %[[MD]]) +// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}", ptr %[[ARG0]], ptr %[[MD]]) // CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0PTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX0PTR]]) // CHECK: %[[CTX1PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX1]], i32 0, i32 0 @@ -1386,33 +1540,33 @@ bb2: // CHECK: ret ptr %[[RET]] // CHECK: } // -// CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.26"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 -// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[SPILL]], i32 0, i32 0 +// 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"(i64 0) // CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) // CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]], ptr %[[MD]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 0 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[SPILL]], i32 0, i32 1 +// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, ptr } poison, ptr @"$s26parametric_casting_closureTA.26.resume.0", 0 +// 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: define {{.*}} ptr @"$s26parametric_casting_closureTA.26.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: define {{.*}} ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 0 +// 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: unwind: -// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -1420,7 +1574,7 @@ bb2: // CHECK: unreachable // // CHECK: resume: -// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.26.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.{{[0-9]+}}.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -1447,39 +1601,185 @@ bb0(%0 : $Base): return %7 : $() } +protocol P0 {} +protocol P1 { associatedtype X : P0 } +protocol P2 { associatedtype Y : P1 } + +// CHECK: define {{.*}} void @partial_apply_complex_generic_function +// CHECK-SAME: (i64 %[[ARG:.*]], ptr %[[TY1:.*]], ptr %[[TY2:.*]], ptr %[[TY3:.*]]) +// CHECK: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8] +// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}} +// CHECK: %[[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: %[[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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] +// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, 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 32, ptr %[[CTXPTR]]) +// CHECK: ret void +// CHECK: } + +// CHECK: define {{.*}} { ptr, ptr } @"$s24complex_generic_functionTA" +// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s24complex_generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[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: %[[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 i64, ptr %[[PA_ARG]] +// CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]]) +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @complex_generic_function(ptr noalias {{.*}} %[[FRAMEPTR]], i64 %[[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) (Int) -> (@yields @in T) +sil @partial_apply_complex_generic_function : $@convention(thin) (Int) -> () { +bb0(%0 : $Int): + %fn = function_ref @complex_generic_function : $@yield_once @convention(thin) (Int) -> (@yields @in T) + %pa = partial_apply %fn (%0) : $@yield_once @convention(thin) (Int) -> (@yields @in T) + (%yield, %token) = begin_apply %pa() : $@yield_once @callee_owned @substituted () -> (@yields @in T) for + end_apply %token as $() + + %result = tuple () + return %result : $() +} + +// CHECK: define {{.*}} void @partial_apply_with_generic_type +// CHECK-SAME: (ptr %[[TY1:.*]], ptr %[[TY2:.*]]) +// CHECK: entry: +// CHECK: %[[CTX:.*]] = alloca [32 x i8] +// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}}) +// CHECK: %[[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"(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 [32 x i8], ptr %[[CTX]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, 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 32, ptr %[[CTXPTR]]) +// CHECK: ret void +// CHECK: } + +// CHECK: define {{.*}} { ptr, ptr } @"$s16generic_functionTA" +// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s16generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[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]]) #3 +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, 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 {} +sil hidden_external @generic_function : $@yield_once @convention(thin) () -> (@yields @in T) +sil @partial_apply_with_generic_type : $@convention(thin) () -> () { +bb0: + %fn = function_ref @generic_function : $@yield_once @convention(thin) () -> (@yields @in T) + %pa = partial_apply %fn >() : $@yield_once @convention(thin) () -> (@yields @in T) + (%yield, %token) = begin_apply %pa() : $@yield_once @callee_owned @substituted () -> (@yields @in T) for > + end_apply %token as $() + %result = tuple () + return %result : $() +} + + // Crash on partial apply of a generic enum. enum GenericEnum { case X(String) case Y(T, T, T, T, T) } -// FIXME: Support coroutine indirect results +sil public @generic_indirect_return : $@yield_once @convention(thin) (Int) -> @owned GenericEnum { +entry(%i : $Int): + %0 = builtin "int_trap"() : $Never + unreachable +} -// sil public @generic_indirect_return : $@yield_once @convention(thin) (Int) -> @owned GenericEnum { -// entry(%i : $Int): -// %0 = builtin "int_trap"() : $Never -// unreachable -// } +// CHECK: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return +// CHECK-SAME: (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 i64 %[[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 () -> @owned GenericEnum { -// bb0(%0 : $Int): -// %fn = function_ref @generic_indirect_return :$@yield_once @convention(thin) (Int) -> @owned GenericEnum -// %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum -// return %pa : $@yield_once @callee_guaranteed () -> @owned GenericEnum -// } +sil @partial_apply_generic_indirect_return : $@convention(thin) (Int) -> @yield_once @callee_guaranteed @substituted () -> @owned GenericEnum for { + bb0(%0 : $Int): + %fn = function_ref @generic_indirect_return :$@yield_once @convention(thin) (Int) -> @owned GenericEnum + %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum + return %pa : $@yield_once @callee_guaranteed @substituted () -> @owned GenericEnum for +} -// sil public @generic_indirect_return2 : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 { -// entry(%i : $Int): -// %0 = builtin "int_trap"() : $Never -// unreachable -// } +enum GenericEnum2 { + case X(String) + case Y(T) +} -// sil @partial_apply_generic_indirect_return2 : $@convention(thin) (Int) -> @yield_once @callee_guaranteed @substituted () -> @owned GenericEnum2 for { -// bb0(%0 : $Int): -// %fn = function_ref @generic_indirect_return2 :$@yield_once @convention(thin) (Int) -> @owned GenericEnum2 -// %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 -// return %pa : $@yield_once @callee_guaranteed @substituted () -> @owned GenericEnum2 for -// } +sil public @generic_indirect_return2 : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 { +entry(%i : $Int): + %0 = builtin "int_trap"() : $Never + unreachable +} + +// CHECK: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return2 +// CHECK-SAME: (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 i64 %[[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 () -> @owned GenericEnum2 for { + bb0(%0 : $Int): + %fn = function_ref @generic_indirect_return2 :$@yield_once @convention(thin) (Int) -> @owned GenericEnum2 + %pa = partial_apply [callee_guaranteed] %fn (%0) : $@yield_once @convention(thin) (Int) -> @owned GenericEnum2 + return %pa : $@yield_once @callee_guaranteed @substituted () -> @owned GenericEnum2 for +} struct SwiftStruct {} @@ -1634,36 +1934,36 @@ bb0(%0 : $*A2): // CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) // CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.30", ptr undef }, ptr %[[BOX]], 1 +// 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.30"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 -// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[SPILL]], i32 0, i32 0 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[PA_ARG]]) // CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[PA_ARG]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_CTX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[SPILL]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.30.resume.0", 0 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0 // CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 // CHECK: ret { ptr, i64 } %[[RET1]] // CHECK: } // -// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.30.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 0 +// 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: unwind: -// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -1671,7 +1971,7 @@ bb0(%0 : $*A2): // CHECK: unreachable // // CHECK: resume: -// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.30.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -1696,7 +1996,7 @@ sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @y // CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.31", ptr %[[BOX]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}", ptr %[[BOX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 // CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) @@ -1704,33 +2004,33 @@ sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @y // CHECK: ret void // CHECK: } // -// CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.31"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 -// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[SPILL]], i32 0, i32 0 +// 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]], align 8 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) // CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[SPILL]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.31.resume.0", 0 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0 // CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 // CHECK: ret { ptr, i64 } %[[RET1]] // CHECK: } // -// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.31.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 0 +// 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: unwind: -// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -1738,7 +2038,7 @@ sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @y // CHECK: unreachable // // CHECK: resume: -// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.31.Frame", ptr %[[FRAME]], i32 0, i32 1 +// 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]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -1923,8 +2223,8 @@ bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) - return %pa_f : $@yield_once @callee_guaranteed (Int64) -> Int64 } +// FIXME: Assertion `LastArgWritten >= adjusted.size()' failed. // 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) @@ -1932,12 +2232,17 @@ bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) - // return %3 : $@yield_once @callee_guaranteed (Int) -> (Int, @error Error) // } -sil @method_with_out_return : $@convention(method) @yield_once (SwiftClass) -> @out Int +// CHECK: 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: } -// FIXME: Support coroutine indirect results -// 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 -// } +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 +} From 1737cb7c480b2db2558a4e10e3f363dfa773d11e Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Fri, 26 Jul 2024 00:45:17 +0900 Subject: [PATCH 05/12] Do not emit a context placeholder for @error results A placeholder goes instead of the context in case of error results, so that thin functions have the same number of arguments as thick ones. Coroutine lowering adds it as part of getCallEmission (via setFromCallee), so we don't need to do it in emitPartialApplicationForwarder. --- lib/IRGen/GenFunc.cpp | 2 +- test/IRGen/partial_apply_coro.sil | 65 +++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 041510ceb6893..f60b253dbf298 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -2200,7 +2200,7 @@ static llvm::Value *emitPartialApplicationForwarder( } // Pass a placeholder for thin function calls. - } else if (origType->hasErrorResult() && !origType->isAsync()) { + } else if (origType->hasErrorResult() && !origType->isAsync() && !origType->isCoroutine()) { emission->addArgument(llvm::UndefValue::get(IGM.RefCountedPtrTy)); } diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index 151aa8df7880d..20c52915d33e0 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -2223,14 +2223,44 @@ bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) - return %pa_f : $@yield_once @callee_guaranteed (Int64) -> Int64 } -// FIXME: Assertion `LastArgWritten >= adjusted.size()' failed. -// 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: define {{.*}} { ptr, ptr } @dont_crash +// CHECK-SAME: (i64 %[[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 i64 %[[ARG]], ptr %[[ARGPTR]] +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s16external_closureTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } +// +// CHECK: define {{.*}} ptr @"$s16external_closureTA" +// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], i64 %[[ARG1:.*]], ptr swiftself %[[PA_CTX_BOX:.*]], ptr noalias nocapture swifterror {{.*}} %[[ERROR:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// 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 i64, ptr %[[PA_ARG]] +// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// CHECK: store ptr null, ptr %[[ERROR]] +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc ptr @external_closure(ptr noalias {{.*}} %[[FRAMEPTR]], i64 %[[ARG1]], i64 %[[ARG2]], ptr swiftself undef, ptr noalias nocapture swifterror {{.*}} %[[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: define {{.*}} { ptr, ptr } @partially_apply_method_with_out_return // CHECK-SAME: (ptr %[[ARG:.*]]) @@ -2246,3 +2276,22 @@ bb(%class : $SwiftClass): %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 } + +// CHECK: define {{.*}} { ptr, ptr } @convert_thin_test(i64 %[[ARG:.*]]) +// CHECK: entry: +// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata +// CHECK: %[[PA_ARG:.*]] = getelementptr inbounds <{ %swift.refcounted, %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// CHECK: %[[ARG_PTR:.*]] = getelementptr inbounds %TSi, ptr %[[PA_ARG]], i32 0, i32 0 +// CHECK: store i64 %[[ARG]], ptr %[[ARG_PTR]] +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s4afunTA", ptr undef }, ptr %[[PA_CTX_BOX]], 1 +// CHECK: ret { ptr, ptr } %[[RET]] +// CHECK: } + +sil @afun : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) +sil @convert_thin_test : $@convention(thin) (Int) -> @yield_once @callee_guaranteed () -> (@error Error, @yields Int) { +bb(%0 : $Int): + %f = function_ref @afun : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) + %c = convert_function %f : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) to $@yield_once @convention(thin) @noescape (Int) -> (@error Error, @yields Int) + %pa = partial_apply [callee_guaranteed] %c(%0) : $@yield_once @convention(thin) @noescape (Int) -> (@error Error, @yields Int) + return %pa : $@yield_once @callee_guaranteed () -> (@error Error, @yields Int) +} From 518b5fb1562de39275c9d3d3b4938d521f8a7f29 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Tue, 30 Jul 2024 21:49:34 +0900 Subject: [PATCH 06/12] Emit unnamed coroutine continuations functions --- lib/IRGen/IRGenMangler.h | 4 -- lib/IRGen/Linking.cpp | 6 ++- test/IRGen/partial_apply_coro.sil | 66 +++++++++++++++++++++++++++--- test/IRGen/yield_once.sil | 7 ++-- test/IRGen/yield_once_big.sil | 15 ++++--- test/IRGen/yield_once_biggish.sil | 7 ++-- test/IRGen/yield_once_indirect.sil | 7 ++-- test/IRGen/yield_result.sil | 11 +++-- 8 files changed, 93 insertions(+), 30 deletions(-) diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h index d777686673ed7..ac646a451a3b5 100644 --- a/lib/IRGen/IRGenMangler.h +++ b/lib/IRGen/IRGenMangler.h @@ -498,10 +498,6 @@ class IRGenMangler : public Mangle::ASTMangler { CanType shapeType, bool isUnique); - std::string mangleCoroutineContinuationPrototype(CanSILFunctionType type) { - return mangleTypeSymbol(type, "TC"); - } - std::string mangleReflectionBuiltinDescriptor(Type type) { const char * const reflectionDescriptorOp = "MB"; if (type->isAnyObject()) { diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index 416105ce056f5..23306d8b90808 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -376,8 +376,10 @@ std::string LinkEntity::mangleAsString() const { } case Kind::CoroutineContinuationPrototype: - return mangler.mangleCoroutineContinuationPrototype( - cast(getType())); + // Emit unnamed functions for coroutine continuation + // prototypes. These are supposed to be replaced by the LLVM + // coroutine lowering pass. + return std::string(); // An Objective-C class reference reference. The symbol is private, so // the mangling is unimportant; it should just be readable in LLVM IR. diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index 20c52915d33e0..b8224c9de451f 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -1429,12 +1429,66 @@ bb0(%x : $*T): return %p : $@yield_once @callee_guaranteed @substituted () -> (@out T, @yields @in T) for } -// FIXME: Cannot mangle free-standing archetypes -// sil @partial_apply_dynamic_with_out_param : $@convention(thin) (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) -// } +// CHECK: 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: %[[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: %[[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: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 4 +// 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: define {{.*}} { ptr, ptr } @"$sTA" +// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: entry: +// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] +// CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$sTA.Frame", ptr %[[SPILL]], i32 0, i32 0 +// CHECK: %[[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: %[[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: %[[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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 +// CHECK: call void @llvm.lifetime.start.p0(i64 32, 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) (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) (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 { } diff --git a/test/IRGen/yield_once.sil b/test/IRGen/yield_once.sil index f3282a6ef4e76..dfa5dad46f94c 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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: call swiftcc void @marker(i32 1000) @@ -43,7 +43,8 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$sIetA_TC" +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc +// CHECK-SAME: void @[[CONT_FN]] // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) diff --git a/test/IRGen/yield_once_big.sil b/test/IRGen/yield_once_big.sil index 84578a1b17b00..60158503840a6 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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr @@ -89,7 +89,8 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC" +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} +// CHECK-SAME: swiftcc void @[[CONT_FN]] // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) @@ -181,8 +182,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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr @@ -236,3 +237,7 @@ unwind: // CHECK: call i1 @llvm.coro.end(ptr [[BEGIN]], i1 false, token none) // CHECK-NEXT: unreachable } + +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} +// CHECK-SAME: swiftcc void @[[CONT_FN]] +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) diff --git a/test/IRGen/yield_once_biggish.sil b/test/IRGen/yield_once_biggish.sil index 72e09248f110f..0c3bf53ee697e 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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], 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) @@ -93,7 +93,8 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC" +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} +// CHECK-SAME: swiftcc void @[[CONT_FN:[0-9]+]] // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) diff --git a/test/IRGen/yield_once_indirect.sil b/test/IRGen/yield_once_indirect.sil index 28af3ed2389c7..871556e0e6fc2 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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], 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) @@ -80,7 +80,8 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC" +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} +// CHECK-SAME: swiftcc void @[[CONT_FN]] // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) diff --git a/test/IRGen/yield_result.sil b/test/IRGen/yield_result.sil index 176efce53119a..2361aeaa75693 100644 --- a/test/IRGen/yield_result.sil +++ b/test/IRGen/yield_result.sil @@ -13,8 +13,8 @@ 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-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) // CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: call swiftcc void @marker(i64 1000) @@ -47,6 +47,9 @@ unwind: // CHECK-NEXT: unreachable } +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} +// CHECK-SAME: swiftcc i64 @[[CONT_FN]] +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: test_coro_ret sil @test_coro_ret : $() -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) { @@ -96,8 +99,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 @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr [[CTX]], ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr [[CTX]], ptr @[[CONT_FN:[0-9]+]], 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:.*]] From 1d1fb9d5cda220b5388f4b8316dc1924259af961 Mon Sep 17 00:00:00 2001 From: Andrew Savonichev Date: Thu, 1 Aug 2024 19:29:32 +0900 Subject: [PATCH 07/12] Add partial_apply_coro tests with resilient types --- test/IRGen/partial_apply_coro.sil | 122 +++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index b8224c9de451f..c2101db069add 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -1,10 +1,12 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=OnoneSimplification -emit-ir %s -o - | %FileCheck %s --check-prefix=CHECK +// 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 %s -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize // REQUIRES: concurrency import Builtin import Swift +import resilient_struct // Basic coroutine: a single yield and no results. // @@ -2191,6 +2193,124 @@ bb0(%x : $*SwiftClassPair): return %t : $() } +// CHECK: 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]], i64 -1 +// CHECK: [[VWT:%.*]] = load ptr, ptr [[VWT_PTR]] +// CHECK: [[FLAGS_PTR:%.*]] = getelementptr inbounds %swift.vwtable, ptr [[VWT]], i32 0, i32 10 +// CHECK: [[FLAGS:%.*]] = load i32, ptr [[FLAGS_PTR]] +// CHECK: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 +// CHECK: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 +// CHECK: = xor i64 [[ALIGNMASK]], -1 +// CHECK: = add i64 16, [[ALIGNMASK]] + +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) (@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) (@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(%32, %34) : $@yield_once @convention(thin) (@in_guaranteed T0, @in_guaranteed T1) -> (@yields @in T0, @yields @in T1) + (%yield1, %yield2, %token) = begin_apply %36() : $@yield_once @callee_guaranteed @substituted () -> (@yields @in T0, @yields @in T1) for + end_apply %token as $() + release_value %36: $@yield_once @callee_guaranteed @substituted () -> (@yields @in T0, @yields @in T1) for + 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) (@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) (@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(%7, %32, %34) : $@yield_once @convention(thin) (@in_guaranteed T0, @in_guaranteed T1, @in_guaranteed T2) -> (@yields @in T0, @out T1, @out T2) + release_value %36: $@yield_once @callee_guaranteed @substituted () -> (@yields @in T0, @out T1, @out T2) for + 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: define {{.*}} { ptr, i64 } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(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): From 68c845a3254b3059d483af2549b50a5b035d5491 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Fri, 2 Aug 2024 17:22:16 -0700 Subject: [PATCH 08/12] Unbreak the test --- test/IRGen/partial_apply_coro.sil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index c2101db069add..d6f6f3e638b6f 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -1381,7 +1381,7 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): // CHECK: store ptr %[[ARGTY]], ptr %[[PA_CTX]] // CHECK: %[[PA_CTX_ARG:.*]] = getelementptr inbounds i8, ptr %[[PA_BOX_ALLOC]], i64 %[[ARGTY_ALIGN4]] // CHECK: %[[INIT_PTR:.*]] = getelementptr inbounds ptr, ptr %[[ARGTY_VW]], i32 4 -// CHECK: %[[INIT:.*]] = load ptr, ptr %[[INIT_PTR]], align 8, !invariant.load !7 +// 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]] From 6d8b0f594fcb51ff2789868f02fcc5becf5e3f91 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Tue, 6 Aug 2024 22:03:17 -0700 Subject: [PATCH 09/12] Fix invalid pointer authentication lowering for coroutine partial apply. Fix tests on arm64e --- lib/IRGen/GenFunc.cpp | 10 +- test/IRGen/partial_apply_coro.sil | 270 ++++++++++++++++-------------- 2 files changed, 149 insertions(+), 131 deletions(-) diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index f60b253dbf298..32cc0216203d2 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1593,10 +1593,14 @@ class CoroPartialApplicationForwarderEmission /// Get the continuation function pointer /// - PointerAuthInfo newAuthInfo = - fnPtr.getAuthInfo().getCorrespondingCodeAuthInfo(); + auto sig = Signature::forCoroutineContinuation(subIGF.IGM, origType); + auto schemaAndEntity = + getCoroutineResumeFunctionPointerAuth(subIGF.IGM, origType); + auto pointerAuth = PointerAuthInfo::emit(subIGF, schemaAndEntity.first, + calleeHandle, + schemaAndEntity.second); FunctionPointer contFn = FunctionPointer::createSigned( - FunctionPointer::Kind::Function, yieldedValues.claimNext(), newAuthInfo, + FunctionPointer::Kind::Function, yieldedValues.claimNext(), pointerAuth, Signature::forCoroutineContinuation(subIGF.IGM, origType)); /// Forward the remaining yields of the wrapped coroutine diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index d6f6f3e638b6f..6589b846453ab 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -1,6 +1,6 @@ // 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 %s -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize +// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=OnoneSimplification -I %t -emit-ir %s -o - | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-cpu // REQUIRES: concurrency @@ -45,9 +45,11 @@ bb2: // CHECK-NEXT: store float %[[ARG]], ptr %[[PA_ARG]], align 8 // CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield1TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield1TA{{.*}}"(ptr noalias dereferenceable(32) %[[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(32) %[[CTXPTR]], i1 false) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) // CHECK-NEXT: call void @swift_release(ptr %[[PA_CTX_BOX]]) @@ -59,7 +61,7 @@ bb2: // // CHECK: define {{.*}} { ptr, float } @"$s6yield1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK-NEXT: entry: -// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc // CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -72,7 +74,7 @@ bb2: // CHECK-NEXT: %[[SPILL2:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK-NEXT: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1 -// CHECK-NEXT: %[[RET_YIELD_PAIR0:.*]] = insertvalue { ptr, float } poison, ptr @"$s6yield1TA.resume.0", 0 +// 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: } @@ -86,7 +88,7 @@ bb2: // CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume // // CHECK: unwind: -// CHECK-NEXT: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 // CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK-NEXT: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -94,7 +96,7 @@ bb2: // CHECK-NEXT: unreachable // // CHECK: resume: -// CHECK-NEXT: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 // CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK-NEXT: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -160,10 +162,10 @@ bb2: // CHECK-NEXT: store float %[[ARG1]], ptr %[[PA_ARG1]], align 8 // CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield2TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield2TA{{.*}}"(ptr noalias dereferenceable(32) %[[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-NEXT: %[[RESULT:.*]] = call swiftcc i64 %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) +// CHECK: %[[RESULT:.*]] = call swiftcc i64 %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) // CHECK-NEXT: call void @swift_release(ptr %[[PA_CTX_BOX]]) // CHECK-NEXT: ret void @@ -174,7 +176,7 @@ bb2: // // CHECK: define {{.*}} { ptr, float } @"$s6yield2TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK-NEXT: entry: -// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK-NEXT: %[[SPILL:.*]] = call ptr @malloc // CHECK-NEXT: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -190,7 +192,7 @@ bb2: // CHECK-NEXT: %[[SPILL2:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK-NEXT: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK-NEXT: %[[YIELD:.*]] = extractvalue { ptr, float } %[[YIELD_PAIR]], 1 -// CHECK-NEXT: %[[RET0:.*]] = insertvalue { ptr, float } poison, ptr @"$s6yield2TA.resume.0", 0 +// 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: } @@ -205,7 +207,7 @@ bb2: // CHECK-NEXT: br i1 %[[UNWIND]], label %unwind, label %resume // // CHECK: unwind: -// CHECK-NEXT: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 // CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK-NEXT: %{{.*}} = call swiftcc i64 %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) @@ -213,7 +215,7 @@ bb2: // CHECK-NEXT: unreachable // // CHECK: resume: -// CHECK-NEXT: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 +// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 // CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 // CHECK-NEXT: %[[RET:.*]] = call swiftcc i64 %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) @@ -268,18 +270,18 @@ bb2: // CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen1TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[ARGBOXED:.*]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen1TA{{.*}}"(ptr noalias dereferenceable(32) %[[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(32) %[[CTXPTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: call void @swift_release(ptr %[[ARGBOXED]]) +// CHECK: call void @swift_release // CHECK: ret void // CHECK: } // // CHECK: define {{.*}} { ptr, ptr } @"$s9yieldgen1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 48) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 @@ -357,6 +359,9 @@ bb0(%0 : $Float): // CHECK: %[[INDIRECT_RET:.*]] = load ptr, ptr %[[SPILL0]], align 8 // CHECK: %[[VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[TYPE]], i64 -1 // CHECK: %[[VW:.*]] = load ptr, ptr %[[VW_PTR]], align 8 +// 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]], align 8 // CHECK: call ptr %[[ASSIGN]](ptr %[[INDIRECT_RET]], ptr %[[ARG]], ptr %[[TYPE]]) @@ -374,7 +379,8 @@ bb2: unwind } -// CHECK: define {{.*}} void @applygen2(float %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} void @applygen2 +// CHECK: (float %[[ARG:.*]]) // CHECK-NEXT: entry: // CHECK: %[[ARG_COPY:.*]] = alloca %TSf, align 4 // CHECK: %[[INDIRECT_RET:.*]] = alloca %TSf, align 4 @@ -388,22 +394,23 @@ bb2: // CHECK: call void @llvm.lifetime.start.p0(i64 4, ptr %[[INDIRECT_RET]]) // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen2TA"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[INDIRECT_RET]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen2TA{{.*}}"(ptr noalias dereferenceable(32) %[[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(32) %[[CTXPTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]]) +// 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: define internal swiftcc { ptr, ptr } @"$s9yieldgen2TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_BOX_CTX:.*]]) +// CHECK-LABEL: define internal swiftcc { ptr, ptr } @"$s9yieldgen2TA" +// CHECK: (ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_BOX_CTX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 48) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[SPILL]], i32 0, i32 2 +// 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:.*]]) @@ -420,14 +427,15 @@ bb2: // CHECK: ret { ptr, ptr } %[[RET1]] // CHECK: } -// CHECK: define {{.*}} void @"$s9yieldgen2TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-LABEL: define {{.*}} void @"$s9yieldgen2TA.resume.0" +// CHECKL (ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 -// CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 2 +// 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: unwind: +// CHECK-LABEL: unwind: // CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0:.*]], align 8 // CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -435,7 +443,7 @@ bb2: // CHECK: call void @free(ptr %[[FRAME]]) // CHECK: unreachable // -// CHECK: resume: +// CHECK-LABEL: resume: // CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 // CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 // CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -470,7 +478,8 @@ class SwiftClass {} sil_vtable SwiftClass {} sil @$s13partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> () -// CHECK: define {{.*}} { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %{{.*}}, ptr %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partially_applyable_to_class( +// CHECK: ptr noalias dereferenceable(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 @@ -494,15 +503,17 @@ bb2: unwind } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_class(ptr %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_class +// CHECK: (ptr %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s28partially_applyable_to_classTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s28partially_applyable_to_classTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // -// CHECK: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA" +// CHECK: (ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 @@ -523,7 +534,7 @@ bb2: // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.Frame", ptr %[[FRAME]], i32 0, i32 0 // CHECK: br i1 %[[UNWIND]], label %unwind, label %resume // -// CHECK: unwind: +// 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]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -531,7 +542,7 @@ bb2: // CHECK: call void @free(ptr %[[FRAME]]) // CHECK: unreachable // -// CHECK: resume: +// 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]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -552,14 +563,14 @@ sil @use_closure_two : $@convention(thin) (@noescape @yield_once @callee_guarant // CHECK: define {{.*}} void @partial_apply_class_on_stack(ptr %[[ARG:.*]]) // CHECK: entry: -// CHECK: call swiftcc void @use_closure(ptr @"$s28partially_applyable_to_classTA.{{[0-9]+}}", ptr %[[ARG]]) +// 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: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc( // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s28partially_applyable_to_classTA.{{[0-9]+}}.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 @@ -644,7 +655,7 @@ bb2: // CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR0]], align 8 // CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr, ptr }>, ptr %[[BOX]], i32 0, i32 2 // CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]], align 8 -// CHECK: call swiftcc void @use_closure_two(ptr @"$s34partially_applyable_to_two_classesTA", ptr %[[BOX]]) +// 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 @@ -652,7 +663,7 @@ bb2: // // CHECK: define {{.*}} { ptr, ptr } @"$s34partially_applyable_to_two_classesTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -741,13 +752,13 @@ bb2: // CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, ptr }>, ptr %[[BOX]], i32 0, i32 1 // CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 // CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[ARG]]) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s22generic_captured_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s22generic_captured_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, i64 } @"$s22generic_captured_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -811,13 +822,13 @@ entry(%i : $*T, %io : $*T): // CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]], align 8 // CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 // CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR2]], align 8 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31generic_captured_and_open_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31generic_captured_and_open_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define internal swiftcc { ptr, ptr } @"$s31generic_captured_and_open_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr noalias %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31generic_captured_and_open_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 @@ -880,13 +891,13 @@ entry(%i : $Int, %c : $SwiftClass): // CHECK: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_param(ptr %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31guaranteed_captured_class_paramTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s31guaranteed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, ptr } @"$s31guaranteed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s31guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 @@ -941,14 +952,15 @@ entry(%i : $Int, %c : $*SwiftClass): // CHECK: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) // CHECK: entry: // CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s40indirect_guaranteed_captured_class_paramTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s40indirect_guaranteed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // -// CHECK: define {{.*}} { ptr, ptr } @"$s40indirect_guaranteed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s40indirect_guaranteed_captured_class_paramTA" +// CHECK: (ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: store ptr %[[PA_CTX_BOX]], ptr %[[SELFPTR]], align 8 @@ -959,18 +971,19 @@ entry(%i : $Int, %c : $*SwiftClass): // CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s40indirect_guaranteed_captured_class_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, ptr } %[[YIELD_PAIR]], 1 -// CHECK: %9 = insertvalue { ptr, ptr } poison, ptr @"$s40indirect_guaranteed_captured_class_paramTA.resume.0", 0 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } %9, ptr %[[YIELD]], 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: define {{.*}} void @"$s40indirect_guaranteed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-LABEL: define {{.*}} void @"$s40indirect_guaranteed_captured_class_paramTA.resume.0" +// CHECK: (ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: // CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 // 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: unwind: +// 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]], align 8 // CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -978,7 +991,7 @@ entry(%i : $Int, %c : $*SwiftClass): // CHECK: call void @free(ptr %[[FRAME]]) // CHECK: unreachable // -// CHECK: resume: +// 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]], align 8 // CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 @@ -1004,14 +1017,14 @@ entry(%i : $Int, %c : $*SwiftClass): // CHECK: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) // CHECK: entry: // CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s38indirect_consumed_captured_class_paramTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s38indirect_consumed_captured_class_paramTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, ptr } @"$s38indirect_consumed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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]]) @@ -1080,13 +1093,13 @@ entry(%i : $Int, %c : $SwiftClassPair): // CHECK: store ptr %[[ARG0]], ptr %[[ARG0PTR]], align 8 // CHECK: %[[ARG1PTR:.*]] = getelementptr inbounds %T18partial_apply_coro14SwiftClassPairV, ptr %[[BOXPTR]], i32 0, i32 1 // CHECK: store ptr %[[ARG1]], ptr %[[ARG1PTR]], align 8 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s36guaranteed_captured_class_pair_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s36guaranteed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, i64 } @"$s36guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -1148,13 +1161,13 @@ entry(%i : $Int, %c : $*SwiftClassPair): // CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) // CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -1165,9 +1178,9 @@ entry(%i : $Int, %c : $*SwiftClassPair): // CHECK: %[[SPILL2:.*]] = getelementptr inbounds %"$s45indirect_guaranteed_captured_class_pair_paramTA.Frame", ptr %[[SPILL]], i32 0, i32 1 // CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %10 = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %11 = insertvalue { ptr, i64 } %10, i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %11 +// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0", 0 +// CHECK: %[[RET:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 +// CHECK: ret { ptr, i64 } %[[RET]] // CHECK: } // // CHECK: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) @@ -1212,13 +1225,13 @@ entry(%i : $Int, %c : $*SwiftClassPair): // CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) // CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s43indirect_consumed_captured_class_pair_paramTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s43indirect_consumed_captured_class_pair_paramTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, i64 } @"$s43indirect_consumed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 56) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -1278,6 +1291,9 @@ entry(%c : $SwiftClass, %a : $*A, %i : $Int): // CHECK: entry: // CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], i64 -1 // CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// 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]], align 8 // do not check computation of align; may be target dependent @@ -1289,20 +1305,20 @@ entry(%c : $SwiftClass, %a : $*A, %i : $Int): // CHECK: store ptr %[[TY]], ptr %[[BOXPTR0]], align 8 // CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 // CHECK: store ptr %[[CTX]], ptr %[[BOXPTR1]], align 8 -// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds i8, ptr %[[BOX]], i64 %8 +// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds i8, ptr %[[BOX]] // CHECK: %[[INITPTR:.*]] = getelementptr inbounds ptr, ptr %[[VWTABLE]], i32 4 // CHECK: %[[INIT:.*]] = load ptr, ptr %[[INITPTR]], align 8 // CHECK: %{{.*}} = call ptr %[[INIT]](ptr noalias %[[BOXPTR2]], ptr noalias %[[ARG0]], ptr %[[TY]]) // CHECK: %[[BOXPTR3:.*]] = getelementptr inbounds i8, ptr %[[BOX]], i64 %{{.*}} // CHECK: %[[BOXPTR3VAL:.*]] = getelementptr inbounds %TSi, ptr %[[BOXPTR3]], i32 0, i32 0 // CHECK: store i64 %[[ARG1]], ptr %[[BOXPTR3VAL]], align 8 -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s35captured_fixed_and_dependent_paramsTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s35captured_fixed_and_dependent_paramsTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define internal swiftcc ptr @"$s35captured_fixed_and_dependent_paramsTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 @@ -1310,13 +1326,16 @@ entry(%c : $SwiftClass, %a : $*A, %i : $Int): // CHECK: store ptr %[[TY]], ptr %[[TY]]1, align 8 // CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], i64 -1 // CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// 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]], align 8 // do not check computation of align; may be target dependent // CHECK: %[[WITNESS_SIZE:.*]] = getelementptr inbounds %swift.vwtable, ptr %[[VWTABLE]], i32 0, i32 8 // CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]], align 8 // do not check computation of size; may be target dependent -// CHECK: %[[PA_CTX2:.8]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// CHECK: %[[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]], align 8 // CHECK: %[[ARG1:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} // CHECK: %[[ARG2PTR0:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} @@ -1360,11 +1379,14 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): return %p : $@yield_once @callee_guaranteed () -> () } -// CHECK: @partial_apply_with_out_param +// 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]], 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_I32:.*]] = load i32, ptr %[[ARGTY_FLAGS_PTR]] // CHECK: %[[ARGTY_FLAGS:.*]] = zext i32 %[[ARGTY_FLAGS_I32]] to i64 @@ -1383,19 +1405,22 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): // 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:.*]] = insertvalue { ptr, ptr } { ptr @"$s28captured_dependent_out_paramTA{{.*}}", ptr undef }, ptr %[[PA_BOX_ALLOC]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // -// CHECK: define {{.*}} @"$s28captured_dependent_out_paramTA" +// 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(i64 40) +// 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: %[[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]], 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 @@ -1431,7 +1456,7 @@ bb0(%x : $*T): return %p : $@yield_once @callee_guaranteed @substituted () -> (@out T, @yields @in T) for } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_dynamic_with_out_param +// 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 @@ -1441,15 +1466,18 @@ bb0(%x : $*T): // CHECK: %[[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: %[[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:.*]] = insertvalue { ptr, ptr } { ptr @"$sTA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } -// CHECK: define {{.*}} { ptr, ptr } @"$sTA" +// 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(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$sTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[PA_ARG1:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 @@ -1535,7 +1563,8 @@ bb2: unwind } -// CHECK: define{{.*}} swiftcc void @test_partial_apply(ptr %[[ARG0:.*]]) +// CHECK-LABEL: define{{.*}} swiftcc void @test_partial_apply +// CHECK-SAME: (ptr %[[ARG0:.*]]) // CHECK: entry: // CHECK: %[[CTX0:.*]] = alloca [32 x i8], align 8 // CHECK: %[[CTX1:.*]] = alloca [32 x i8], align 8 @@ -1543,20 +1572,21 @@ bb2: // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX0PTR]]) // CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) // CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 -// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}", ptr %[[ARG0]], ptr %[[MD]]) +// CHECK: %[[RESUME0:.*]] = call swiftcc ptr @receive_closure(ptr noalias dereferenceable(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}{{.*}}", ptr %[[ARG0]], ptr %[[MD]]) // CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0PTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX0PTR]]) // CHECK: %[[CTX1PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX1]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX1PTR]]) -// CHECK: %[[RESUME1:.*]] = call swiftcc ptr @receive_closure2(ptr noalias dereferenceable(32) %[[CTX1PTR]], ptr @"$s26parametric_casting_closureTA", ptr null, ptr %[[MD]]) +// CHECK: %[[RESUME1:.*]] = call swiftcc ptr @receive_closure2(ptr noalias dereferenceable(32) %[[CTX1PTR]], ptr @"$s26parametric_casting_closureTA{{.*}}", ptr null, ptr %[[MD]]) // CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1PTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX1PTR]]) // CHECK: ret void // CHECK: } // -// CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA" +// CHECK-SAME: (ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %1, ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s26parametric_casting_closureTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) @@ -1598,7 +1628,7 @@ bb2: // // CHECK: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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"(i64 0) @@ -1661,7 +1691,7 @@ protocol P0 {} protocol P1 { associatedtype X : P0 } protocol P2 { associatedtype Y : P1 } -// CHECK: define {{.*}} void @partial_apply_complex_generic_function +// CHECK-LABEL: define {{.*}} void @partial_apply_complex_generic_function // CHECK-SAME: (i64 %[[ARG:.*]], ptr %[[TY1:.*]], ptr %[[TY2:.*]], ptr %[[TY3:.*]]) // CHECK: entry: // CHECK: %[[CTX:.*]] = alloca [32 x i8] @@ -1677,7 +1707,7 @@ protocol P2 { associatedtype Y : P1 } // CHECK: store i64 %[[ARG]], ptr %[[PA_ARG_PTR]] // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s24complex_generic_functionTA"(ptr noalias {{.*}} %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// 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) @@ -1685,10 +1715,10 @@ protocol P2 { associatedtype Y : P1 } // CHECK: ret void // CHECK: } -// CHECK: define {{.*}} { ptr, ptr } @"$s24complex_generic_functionTA" +// 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(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s24complex_generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 @@ -1736,7 +1766,7 @@ bb0(%0 : $Int): // CHECK: store ptr %[[MD]], ptr %[[PA_CTX]] // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s16generic_functionTA"(ptr noalias {{.*}} %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// 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) @@ -1747,7 +1777,7 @@ bb0(%0 : $Int): // CHECK: define {{.*}} { ptr, ptr } @"$s16generic_functionTA" // CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// 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: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 @@ -1797,7 +1827,7 @@ entry(%i : $Int): // 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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s23generic_indirect_returnTA", ptr undef }, ptr %[[PA_CTX_BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s23generic_indirect_returnTA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } @@ -1826,7 +1856,7 @@ entry(%i : $Int): // 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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s24generic_indirect_return2TA", ptr undef }, ptr %[[PA_CTX_BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s24generic_indirect_return2TA{{.*}}", ptr undef }, ptr %[[PA_CTX_BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } @@ -1848,13 +1878,13 @@ entry(%t : $@thin SwiftStruct.Type, %c : $SwiftClass): // CHECK: define{{.*}} swiftcc { ptr, ptr } @partial_apply_thin_type(ptr %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s3funTA", ptr undef }, ptr %[[ARG]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s3funTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, ptr } @"$s3funTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 @@ -1919,14 +1949,14 @@ entry(%a : $*A2): } // CHECK: define {{.*}} { ptr, ptr } @repo(ptr noalias nocapture dereferenceable(8) %[[ARG:.*]]) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s7amethodTA", ptr undef }, ptr %{{.*}}, 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s7amethodTA{{.*}}", ptr undef }, ptr %{{.*}}, 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // // CHECK: define {{.*}} { ptr, ptr, ptr } @"$s7amethodTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[SELF:.*]], ptr noalias nocapture swifterror dereferenceable(8) %[[ERRORPTR:.*]]) // CHECK: entry: // CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[SPILL]], i32 0, i32 0 // CHECK: store ptr %[[SELF]], ptr %[[SELFPTR]], align 8 @@ -1990,13 +2020,13 @@ bb0(%0 : $*A2): // CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) // CHECK: %[[BOXPTR:.*]] = getelementptr inbounds <{ %swift.refcounted, %T18partial_apply_coro14SwiftClassPairV }>, ptr %[[BOX]], i32 0, i32 1 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}", ptr undef }, ptr %[[BOX]], 1 +// 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -2052,7 +2082,7 @@ sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @y // CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}", ptr %[[BOX]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}{{.*}}", ptr %[[BOX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 // CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) @@ -2062,7 +2092,7 @@ sil public_external @use_closure2 : $@yield_once @convention(thin) (@noescape @y // // CHECK: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -2129,18 +2159,18 @@ entry(%i : $Int, %p : $*SwiftClassPair): // CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s37indirect_in_captured_class_pair_paramTA", ptr %[[BOX]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s37indirect_in_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 // CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) // CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %8 = call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]]) +// CHECK: call ptr @"$s18partial_apply_coro14SwiftClassPairVWOh"(ptr %[[ARG]]) // CHECK: ret void // CHECK: } // // CHECK: define {{.*}} { ptr, i64 } @"$s37indirect_in_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -2193,12 +2223,15 @@ bb0(%x : $*SwiftClassPair): return %t : $() } -// CHECK: define {{.*}} void @test_initial_offset +// 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]], i64 -1 -// CHECK: [[VWT:%.*]] = load ptr, ptr [[VWT_PTR]] -// CHECK: [[FLAGS_PTR:%.*]] = getelementptr inbounds %swift.vwtable, ptr [[VWT]], i32 0, i32 10 +// 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 // CHECK: [[FLAGS:%.*]] = load i32, ptr [[FLAGS_PTR]] // CHECK: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 // CHECK: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 @@ -2326,7 +2359,7 @@ entry(%i : $Int, %ic : $*SwiftClassPair): // CHECK: store ptr %[[ARG]], ptr %[[BOXPTR]], align 8 // CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 // CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s46indirect_in_constant_captured_class_pair_paramTA", ptr %[[BOX]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s46indirect_in_constant_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]]) // CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 // CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 // CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) @@ -2337,7 +2370,7 @@ entry(%i : $Int, %ic : $*SwiftClassPair): // // CHECK: define {{.*}} { ptr, i64 } @"$s46indirect_in_constant_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 // 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 @@ -2397,21 +2430,21 @@ bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) - return %pa_f : $@yield_once @callee_guaranteed (Int64) -> Int64 } -// CHECK: define {{.*}} { ptr, ptr } @dont_crash +// CHECK-LABEL: define {{.*}} { ptr, ptr } @dont_crash // CHECK-SAME: (i64 %[[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 i64 %[[ARG]], ptr %[[ARGPTR]] -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s16external_closureTA", ptr undef }, ptr %[[BOX]], 1 +// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s16external_closureTA{{.*}}", ptr undef }, ptr %[[BOX]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // -// CHECK: define {{.*}} ptr @"$s16external_closureTA" +// CHECK-LABEL: define {{.*}} ptr @"$s16external_closureTA" // CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], i64 %[[ARG1:.*]], ptr swiftself %[[PA_CTX_BOX:.*]], ptr noalias nocapture swifterror {{.*}} %[[ERROR:.*]]) // CHECK: entry: -// CHECK: %[[SPILL:.*]] = call ptr @malloc(i64 40) +// 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 @@ -2436,10 +2469,10 @@ bb0(%0 : $Int): return %3 : $@yield_once @callee_guaranteed (Int) -> (Int, @error Error) } -// CHECK: define {{.*}} { ptr, ptr } @partially_apply_method_with_out_return +// 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:.*]] = insertvalue { ptr, ptr } { ptr @"$s22method_with_out_returnTA{{.*}}", ptr undef }, ptr %[[ARG]], 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } @@ -2450,22 +2483,3 @@ bb(%class : $SwiftClass): %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 } - -// CHECK: define {{.*}} { ptr, ptr } @convert_thin_test(i64 %[[ARG:.*]]) -// CHECK: entry: -// CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata -// CHECK: %[[PA_ARG:.*]] = getelementptr inbounds <{ %swift.refcounted, %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 -// CHECK: %[[ARG_PTR:.*]] = getelementptr inbounds %TSi, ptr %[[PA_ARG]], i32 0, i32 0 -// CHECK: store i64 %[[ARG]], ptr %[[ARG_PTR]] -// CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s4afunTA", ptr undef }, ptr %[[PA_CTX_BOX]], 1 -// CHECK: ret { ptr, ptr } %[[RET]] -// CHECK: } - -sil @afun : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) -sil @convert_thin_test : $@convention(thin) (Int) -> @yield_once @callee_guaranteed () -> (@error Error, @yields Int) { -bb(%0 : $Int): - %f = function_ref @afun : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) - %c = convert_function %f : $@yield_once @convention(thin) (Int) -> (@error Error, @yields Int) to $@yield_once @convention(thin) @noescape (Int) -> (@error Error, @yields Int) - %pa = partial_apply [callee_guaranteed] %c(%0) : $@yield_once @convention(thin) @noescape (Int) -> (@error Error, @yields Int) - return %pa : $@yield_once @callee_guaranteed () -> (@error Error, @yields Int) -} From 975e6feb0707ca3a07fbd087661e1076dd58dc3f Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Tue, 6 Aug 2024 22:11:54 -0700 Subject: [PATCH 10/12] Add documentation note for partial_apply of a coroutine --- docs/SIL.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/SIL.rst b/docs/SIL.rst index 76f31b13ba506..cf613fe386cd2 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -804,7 +804,7 @@ the ``@yields`` attribute. A yielded value may have a convention attribute, taken from the set of parameter attributes and interpreted as if the yield site were calling back to the calling function. -Currently, a coroutine may not have normal results. +In addition to yielded values a coroutine could also have normal results. Coroutine functions may be used in many of the same ways as normal function values. However, they cannot be called with the standard @@ -6330,6 +6330,16 @@ callee function (and thus said signature). Instead: ``@inout_aliasable`` parameter convention is used when a ``@noescape`` closure captures an ``inout`` argument. +**Coroutines** ``partial_apply`` could be used to create closures over +coroutines. Overall, the ``partial_apply`` of a coroutine is straightforward: it +is another coroutine that captures arguments passed to the ``partial_apply`` +instruction. This closure applies the original coroutine (similar to the +``begin_apply`` instruction) for yields (suspend) and yields the resulting +values. Then it calls the original coroutine continuation for return or unwind, +and forwards the results (if any) to the caller as well. Currently only the +autodiff transformation produces ``partial_apply`` for coroutines while +differentiating modify accessors. + **NOTE:** If the callee is generic, all of its generic parameters must be bound by the given substitution list. The arguments are given with these generic substitutions applied, and the resulting closure is of concrete function type From 85810bf6e1501fc52710b3ee285da90c130b50f0 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 7 Aug 2024 23:05:13 -0700 Subject: [PATCH 11/12] Refactor all the tests to be robust wrt platform differences --- test/IRGen/partial_apply_coro.sil | 1599 ++++++++++++++++------------- 1 file changed, 868 insertions(+), 731 deletions(-) diff --git a/test/IRGen/partial_apply_coro.sil b/test/IRGen/partial_apply_coro.sil index 6589b846453ab..807a2d869ad7f 100644 --- a/test/IRGen/partial_apply_coro.sil +++ b/test/IRGen/partial_apply_coro.sil @@ -8,16 +8,21 @@ import Builtin import Swift import resilient_struct + // Basic coroutine: a single yield and no results. // -// CHECK: define {{.*}} { ptr, float } @yield1(ptr noalias dereferenceable(32) %{{.*}}, float %[[ARG:.*]]) +// 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: define {{.*}} void @yield1.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, i1 %[[UNWIND:.*]]) +// 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: } @@ -36,22 +41,23 @@ bb2: // Original caller: calls the partial apply wrapper // -// CHECK: define {{.*}} void @apply1(float %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} void @apply1 +// CHECK-SAME: (float %[[ARG:.*]]) // CHECK-NEXT: entry: -// CHECK-NEXT: %[[CTX:.*]] = alloca [32 x i8], align 8 -// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata, i32 0, i32 2), i64 20, i64 7) +// 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]], align 8 -// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield1TA{{.*}}"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// 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(32) %[[CTXPTR]], i1 false) -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: } @@ -59,20 +65,21 @@ bb2: // Partial apply wrapper: call the coroutine and forward yields and the resume // function. // -// CHECK: define {{.*}} { ptr, float } @"$s6yield1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield1(ptr noalias dereferenceable(32) %[[FRAMEPTR]], float %[[ARG]]) +// 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]], align 8 +// 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 @@ -81,25 +88,27 @@ bb2: // // Partial apply resume: call the underlying coroutine for resume and unwind. // -// CHECK: define {{.*}} void @"$s6yield1TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[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]], align 8 +// 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: unwind: +// CHECK-LABEL: unwind: // CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 -// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK-NEXT: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// CHECK-LABEL: resume: // CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK-NEXT: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -120,21 +129,30 @@ bb0(%0 : $Float): // Coroutine with a yield and a result // -// CHECK: define {{.*}} { ptr, float } @yield2(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], float %[[ARG1:.*]]) +// 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-NEXT: store i64 %[[ARG0]], ptr %[[FRAME]], align 8 +// 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: define {{.*}} i64 @yield2.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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-NEXT: %[[RET:.*]] = load i64, ptr %[[FRAME]], align 8 -// CHECK-NEXT: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], i64 undef, i64 %[[RET]] -// CHECK-NEXT: ret i64 %[[RET_SEL]] +// 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) { @@ -150,23 +168,27 @@ bb2: // Original caller: calls the partial apply wrapper for both yields and results. // -// CHECK: define {{.*}} void @apply2(i64 %[[ARG0:.*]], float %[[ARG1:.*]]) +// 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 [32 x i8], align 8 -// CHECK-NEXT: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 28, i64 7) +// 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-NEXT: store i64 %[[ARG0]], ptr %[[PA_ARG0]], align 8 +// 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]], align 8 -// CHECK-NEXT: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @"$s6yield2TA{{.*}}"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself %[[PA_CTX_BOX]]) +// 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: %[[RESULT:.*]] = call swiftcc i64 %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) -// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: } @@ -174,23 +196,24 @@ bb2: // Partial apply wrapper: receive two captured arguments, call the coroutine and // forward yields and the resume function. // -// CHECK: define {{.*}} { ptr, float } @"$s6yield2TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 i64, ptr %[[ARG0PTR]], align 8 +// 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]], align 8 -// CHECK-NEXT: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK-NEXT: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, float } @yield2(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], float %[[ARG1]]) +// 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]], align 8 +// 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 @@ -200,27 +223,30 @@ bb2: // Partial apply resume: call the underlying coroutine for resume and return the // result. Call the resume function for unwind as well. // -// CHECK: define {{.*}} i64 @"$s6yield2TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// CHECK-LABEL: unwind: // CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK-NEXT: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 -// CHECK-NEXT: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK-NEXT: %{{.*}} = call swiftcc i64 %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// CHECK-LABEL: resume: // CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s6yield2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK-NEXT: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK-NEXT: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK-NEXT: %[[RET:.*]] = call swiftcc i64 %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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 i64 %[[RET]] +// CHECK-NEXT: ret [[ARGTYPE]] %[[RET]] // CHECK-NEXT: } // sil [ossa] @apply2 : $(Int, Float) -> () { @@ -238,16 +264,19 @@ bb0(%0 : $Int, %1 : $Float): } // Coroutine with a generic yield and no results -// CHECK: define {{.*}} { ptr, ptr } @yieldgen1(ptr noalias dereferenceable(32) %{{.*}}, ptr noalias %[[ARG1:.*]], ptr %[[ARG2:.*]]) +// 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, align 8 -// CHECK-NEXT: store ptr %[[ARG2]], ptr %[[SPILL_ARG2]], align 8 +// 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: define {{.*}} void @yieldgen1.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, i1 %[[UNWIND:.*]]) +// 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 @@ -265,56 +294,62 @@ bb2: unwind } -// CHECK: define {{.*}} void @applygen1(float %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} void @applygen1 +// CHECK-SAMEL (float %[[ARG:.*]]) // CHECK-NEXT: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen1TA{{.*}}"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr swiftself +// 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(32) %[[CTXPTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: define {{.*}} { ptr, ptr } @"$s9yieldgen1TA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen1(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr noalias %[[PA_CTX_BOX2:.*]], ptr @"$sSfN") +// 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, i32 1 -// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]], align 8 +// 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: define {{.*}} void @"$s9yieldgen1TA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) -// CHECK: entryresume.0: -// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: unwind: -// CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 -// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX]], i1 true) +// 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: resume: -// CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen1TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX]], i1 false) +// 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: } @@ -338,32 +373,35 @@ bb0(%0 : $Float): // Coroutine with a generic yield and a generic indirect result // -// CHECK: define {{.*}} { ptr, ptr } @yieldgen2(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr noalias %[[ARG:.*]], ptr %[[TYPE:.*]]) +// 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]], align 8 +// CHECK: store ptr %[[TYPE]], ptr %[[SPILL2]] // CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1 -// CHECK: store ptr %[[ARG]], ptr %[[SPILL1]], align 8 +// 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]], align 8 +// 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: define {{.*}} void @yieldgen2.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// CHECK: %[[TYPE:.*]] = load ptr, ptr %[[SPILL2]] // CHECK: %[[SPILL1:.*]] = getelementptr inbounds %yieldgen2.Frame, ptr %[[CTX]], i32 0, i32 1 -// CHECK: %[[ARG:.*]] = load ptr, ptr %[[SPILL1]], align 8 +// 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]], align 8 -// CHECK: %[[VW_PTR:.*]] = getelementptr inbounds ptr, ptr %[[TYPE]], i64 -1 -// CHECK: %[[VW:.*]] = load ptr, ptr %[[VW_PTR]], align 8 +// 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]], align 8 +// CHECK: %[[ASSIGN:.*]] = load ptr, ptr %[[ASSIGN_PTR]] // CHECK: call ptr %[[ASSIGN]](ptr %[[INDIRECT_RET]], ptr %[[ARG]], ptr %[[TYPE]]) // sil @yieldgen2 : $@yield_once @convention(thin) (@in T) -> (@yields @in T, @out T) { @@ -380,25 +418,26 @@ bb2: } // CHECK-LABEL: define {{.*}} void @applygen2 -// CHECK: (float %[[ARG:.*]]) +// CHECK-SAME: (float %[[ARG:.*]]) // CHECK-NEXT: entry: // CHECK: %[[ARG_COPY:.*]] = alloca %TSf, align 4 // CHECK: %[[INDIRECT_RET:.*]] = alloca %TSf, align 4 -// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 +// 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: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[PA_CTX_ARG]], ptr align 4 %[[ARG_COPY]], i64 4, i1 false) +// 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 [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @"$s9yieldgen2TA{{.*}}"(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[INDIRECT_RET]], ptr swiftself +// 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(32) %[[CTXPTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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]]) @@ -406,21 +445,22 @@ bb2: // CHECK: } // CHECK-LABEL: define internal swiftcc { ptr, ptr } @"$s9yieldgen2TA" -// CHECK: (ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[INDIRECT_RET:.*]], ptr swiftself %[[PA_BOX_CTX:.*]]) +// 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]], align 8 +// 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: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[SPILL2:.*]], ptr align 8 %[[ARG]], i64 4, i1 false) -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @yieldgen2(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[INDIRECT_RET]], ptr noalias %[[SPILL2]], ptr @"$sSfN") +// 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, i32 1 -// CHECK: store ptr %[[RESUME]], ptr %[[SPILL1]], align 8 +// 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 @@ -428,26 +468,28 @@ bb2: // CHECK: } // CHECK-LABEL: define {{.*}} void @"$s9yieldgen2TA.resume.0" -// CHECKL (ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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, i32 1 -// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0:.*]], align 8 -// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX]], i1 true) +// 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: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s9yieldgen2TA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK: %[[CTX:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX]], i1 false) +// 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: } @@ -472,6 +514,7 @@ bb0(%0 : $Float): return %r : $() } + // Tests below are ported from partial_apply.sil and adapted to use coroutines. class SwiftClass {} @@ -479,14 +522,16 @@ sil_vtable SwiftClass {} sil @$s13partial_apply10SwiftClassCfD : $@convention(method) (SwiftClass) -> () // CHECK-LABEL: define {{.*}} { ptr, ptr } @partially_applyable_to_class( -// CHECK: ptr noalias dereferenceable(32) %{{.*}}, ptr %[[ARG:.*]]) +// 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: define {{.*}} void @partially_applyable_to_class.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %{{.*}}, i1 %[[UNWIND:.*]]) +// 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: } @@ -504,49 +549,50 @@ bb2: } // CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_class -// CHECK: (ptr %[[ARG:.*]]) +// 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: (ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %[[FRAMEPTR]], 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 } @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]], align 8 +// 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: define {{.*}} void @"$s28partially_applyable_to_classTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -561,49 +607,52 @@ entry(%c : $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: define {{.*}} void @partial_apply_class_on_stack(ptr %[[ARG:.*]]) +// 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: define {{.*}} { ptr, ptr } @"$s28partially_applyable_to_classTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_class(ptr noalias dereferenceable(32) %[[FRAMEPTR]], 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 } @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]], align 8 +// 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: define {{.*}} void @"$s28partially_applyable_to_classTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) -// CHECK: entryresume.0: -// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -620,19 +669,21 @@ entry(%a : $SwiftClass): return %t : $() } -// CHECK: define {{.*}} { ptr, ptr } @partially_applyable_to_two_classes(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %1, ptr %[[ARG:.*]]) +// 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]], align 8 +// 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: define {{.*}} ptr @partially_applyable_to_two_classes.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// CHECK: %[[ARG:.*]] = load ptr, ptr %[[FRAME]] // CHECK: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], ptr undef, ptr %[[ARG]] // CHECK: ret ptr %[[RET_SEL]] // CHECK: } @@ -648,59 +699,62 @@ bb2: unwind } -// CHECK: define {{.*}} void @partial_apply_two_classes_on_stack(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// CHECK-LABEL: define {{.*}} void @partial_apply_two_classes_on_stack +// CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) // CHECK: entry: -// CHECK: %[[BOX:.*]] = alloca i8, i64 32, align 16 +// 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]], align 8 +// 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]], align 8 +// 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: define {{.*}} { ptr, ptr } @"$s34partially_applyable_to_two_classesTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @partially_applyable_to_two_classes(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[ARG0]], ptr %[[ARG1]]) +// 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]], align 8 +// 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: define {{.*}} ptr @"$s34partially_applyable_to_two_classesTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -718,14 +772,17 @@ entry(%a : $SwiftClass, %b: $SwiftClass): return %t : $() } -// CHECK: define {{.*}} { ptr, i64 } @generic_captured_param(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr %[[ARG1:.*]], ptr %[[ARG2:.*]]) +// 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, i64 } poison, ptr @generic_captured_param.resume.0, 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[ARG0]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @generic_captured_param.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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: } @@ -742,58 +799,62 @@ bb2: unwind } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_generic_capture(i64 %[[ARG0:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_generic_capture +// CHECK-SAME: ([[ARG_TYPE]] %[[ARG0:.*]]) // CHECK: entry: -// CHECK: %[[ARG:.*]] = alloca %TSi, align 8 -// CHECK: call void @llvm.lifetime.start.p0(i64 8, ptr %[[ARG]]) +// 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 i64 %[[ARG0]], ptr %[[ARGPTR]], align 8 -// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 24, i64 7) +// 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]], align 8 -// CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[ARG]]) +// 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: define {{.*}} { ptr, i64 } @"$s22generic_captured_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @generic_captured_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr %[[ARG1]], ptr @"$sSiN") -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s22generic_captured_paramTA.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @"$s22generic_captured_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -808,64 +869,68 @@ entry(%x : $Int): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int) } -// CHECK: define {{.*}} { ptr, ptr } @generic_captured_and_open_param(ptr noalias dereferenceable(32) %0, ptr noalias %1, ptr %2, ptr %T) +// 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) (@in T, @inout T) -> (@yields @in T) { entry(%i : $*T, %io : $*T): %0 = builtin "int_trap"() : $Never unreachable } -// CHECK: define{{.*}} swiftcc { ptr, ptr } @partial_apply_open_generic_capture(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// 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.{{.*}}, i32 0, i32 2), i64 32, i64 7) -// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1 -// CHECK: store ptr %[[ARG1]], ptr %[[BOXPTR1]], align 8 -// CHECK: %[[BOXPTR2:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 -// CHECK: store ptr %[[ARG0]], ptr %[[BOXPTR2]], align 8 +// 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: define internal swiftcc { ptr, ptr } @"$s31generic_captured_and_open_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr noalias %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 -// CHECK: %[[ARG1:.*]] = load ptr, ptr %[[PA_CTX]], align 8 -// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 -// CHECK: %[[ARG2:.*]] = load ptr, ptr %[[PA_CTX2]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @generic_captured_and_open_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr noalias %[[ARG0]], ptr %[[ARG2]], ptr %[[ARG1]]) +// 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]], align 8 +// 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: define internal swiftcc void @"$s31generic_captured_and_open_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -882,55 +947,59 @@ entry(%a : $*T): /* as the partial apply context. */ /*****************************************************************************/ -// CHECK: define {{.*}} { ptr, ptr } @guaranteed_captured_class_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr %2) +// 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: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_param(ptr %[[ARG:.*]]) +// 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: define {{.*}} { ptr, ptr } @"$s31guaranteed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @guaranteed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], 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 } @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]], align 8 +// 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: define {{.*}} void @"$s31guaranteed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -942,34 +1011,36 @@ bb0(%x : $SwiftClass): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields SwiftClass) } -// CHECK: define {{.*}} { ptr, ptr } @indirect_guaranteed_captured_class_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(8) %2) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @indirect_guaranteed_captured_class_param +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %0, [[ARGTYPE:i32|i64]] %1, ptr noalias nocapture 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: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[ARGPTR_SIZE]]) %[[ARGPTR:.*]]) // CHECK: entry: -// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 +// 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(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// CHECK: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], [[ARG_TYPE]] %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: -// CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 +// CHECK: %[[SELFPTR:.*]] = alloca ptr // CHECK: %[[SPILL:.*]] = call ptr @malloc -// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_guaranteed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(8) %[[SELFPTR]]) +// 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 nocapture 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]], align 8 +// 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 @@ -977,25 +1048,25 @@ entry(%i : $Int, %c : $*SwiftClass): // CHECK: } // // CHECK-LABEL: define {{.*}} void @"$s40indirect_guaranteed_captured_class_paramTA.resume.0" -// CHECK: (ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// CHECK-SAME: (ptr noalias noundef nonnull align [[ARGPTR_SIZE]] dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], i1 %[[UNWIND:.*]]) // CHECK: entryresume.0: -// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1007,59 +1078,63 @@ bb0(%x : $*SwiftClass): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields SwiftClass) } -// CHECK: define {{.*}} { ptr, ptr } @indirect_consumed_captured_class_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(8) %2) +// 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 nocapture 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: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_param(ptr noalias nocapture dereferenceable(8) %[[ARGPTR:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[ARGPTR_SIZE]]) %[[ARGPTR:.*]]) // CHECK: entry: -// CHECK: %[[ARG:.*]] = load ptr, ptr %[[ARGPTR]], align 8 +// 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: define {{.*}} { ptr, ptr } @"$s38indirect_consumed_captured_class_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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, align 8 +// CHECK: %[[SELFPTR:.*]] = alloca ptr // CHECK: %[[SPILL:.*]] = call ptr @malloc -// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @indirect_consumed_captured_class_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(8) %[[SELFPTR]]) +// 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 nocapture 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]], align 8 +// 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: define {{.*}} void @"$s38indirect_consumed_captured_class_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1078,66 +1153,71 @@ bb0(%x : $*SwiftClass): struct SwiftClassPair { var x: SwiftClass, y: SwiftClass } -// CHECK: define {{.*}} { ptr, i64 } @guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr %2, ptr %3) +// 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: define {{.*}} { ptr, ptr } @partial_apply_guaranteed_class_pair_param(ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// 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.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// 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]], align 8 +// 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]], align 8 +// 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: define {{.*}} { ptr, i64 } @"$s36guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr %[[ARG1]], ptr %[[ARG2]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s36guaranteed_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @"$s36guaranteed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1149,59 +1229,65 @@ bb0(%x : $SwiftClassPair): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int) } -// CHECK: define {{.*}} { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(16) %2) +// 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 nocapture 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: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_guaranteed_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// 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.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) +// 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 [32 x i8], ptr %[[SPILL1]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %1, ptr noalias nocapture dereferenceable(16) %[[PA_CTX]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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 nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %[[RET:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET]] +// 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: define {{.*}} void @"$s45indirect_guaranteed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1213,62 +1299,68 @@ bb0(%x : $*SwiftClassPair): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int) } -// CHECK: define {{.*}} { ptr, i64 } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(16) %2) +// 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 nocapture 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: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_indirect_consumed_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// 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.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) +// 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: define {{.*}} { ptr, i64 } @"$s43indirect_consumed_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 16, ptr %[[SPILL1]]) +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %1, ptr noalias nocapture dereferenceable(16) %[[SPILL1]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 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, [[ARG_TYPE]] } @indirect_consumed_captured_class_pair_param(ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[FRAMEPTR]], [[ARG_TYPE]] %1, ptr noalias nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @"$s43indirect_consumed_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1280,94 +1372,100 @@ bb0(%x : $*SwiftClassPair): return %p : $@yield_once @callee_guaranteed (Int) -> (@yields Int) } -// CHECK: define {{.*}} ptr @captured_fixed_and_dependent_params(ptr noalias dereferenceable(32) %0, ptr %1, ptr noalias %2, i64 %3, ptr %A) +// 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) (@guaranteed SwiftClass, @in_guaranteed A, Int) -> () { entry(%c : $SwiftClass, %a : $*A, %i : $Int): %0 = builtin "int_trap"() : $Never unreachable } -// CHECK: define{{.*}} swiftcc { ptr, ptr } @partial_apply_indirect_non_fixed_layout(ptr %[[CTX:.*]], ptr noalias %[[ARG0:.*]], i64 %[[ARG1:.*]], ptr %[[TY:.*]]) +// 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]], i64 -1 -// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// 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]], align 8 +// 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 -// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]], align 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{{.*}}, i32 0, i32 2), i64 %{{.*}}, i64 %{{.*}}) -// CHECK: %[[BOXPTR0:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 1 -// CHECK: store ptr %[[TY]], ptr %[[BOXPTR0]], align 8 -// CHECK: %[[BOXPTR1:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8], ptr }>, ptr %[[BOX]], i32 0, i32 2 -// CHECK: store ptr %[[CTX]], ptr %[[BOXPTR1]], align 8 +// 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]], align 8 +// 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]], i64 %{{.*}} +// CHECK: %[[BOXPTR3:.*]] = getelementptr inbounds i8, ptr %[[BOX]], {{i32|i64}} %{{.*}} // CHECK: %[[BOXPTR3VAL:.*]] = getelementptr inbounds %TSi, ptr %[[BOXPTR3]], i32 0, i32 0 -// CHECK: store i64 %[[ARG1]], ptr %[[BOXPTR3VAL]], align 8 +// 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: define internal swiftcc ptr @"$s35captured_fixed_and_dependent_paramsTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s35captured_fixed_and_dependent_paramsTA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: %[[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]], align 8 -// CHECK: store ptr %[[TY]], ptr %[[TY]]1, align 8 -// CHECK: %[[TYMD:.*]] = getelementptr inbounds ptr, ptr %[[TY]], i64 -1 -// CHECK: %[[VWTABLE:.*]] = load ptr, ptr %[[TYMD]], align 8 +// 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]], align 8 +// 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 -// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]], align 8 // do not check computation of size; may be target dependent -// CHECK: %[[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]], align 8 -// CHECK: %[[ARG1:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} -// CHECK: %[[ARG2PTR0:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} +// 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 i64, ptr %[[ARG2PTR1]], align 8 -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[RESUME:.*]] = call swiftcc ptr @captured_fixed_and_dependent_params(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[ARG0]], ptr noalias %[[ARG1]], i64 %[[ARG2]], ptr %T) +// 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]], align 8 +// CHECK: store ptr %[[RESUME]], ptr %[[SPILL2]] // CHECK: ret ptr @"$s35captured_fixed_and_dependent_paramsTA.resume.0" // CHECK: } // -// CHECK: define internal swiftcc void @"$s35captured_fixed_and_dependent_paramsTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1382,26 +1480,21 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): // 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]], i64 -1 +// 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_I32:.*]] = load i32, ptr %[[ARGTY_FLAGS_PTR]] -// CHECK: %[[ARGTY_FLAGS:.*]] = zext i32 %[[ARGTY_FLAGS_I32]] to i64 -// CHECK: %[[ARGTY_ALIGN1:.*]] = and i64 %[[ARGTY_FLAGS]], 255 -// CHECK: %[[ARGTY_ALIGN2:.*]] = xor i64 %[[ARGTY_ALIGN1]], -1 -// CHECK: %[[ARGTY_ALIGN3:.*]] = add i64 24, %[[ARGTY_ALIGN1]] -// CHECK: %[[ARGTY_ALIGN4:.*]] = and i64 %[[ARGTY_ALIGN3]], %[[ARGTY_ALIGN2]] +// 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 -// CHECK: %[[ARGTY_SIZE1:.*]] = load i64, ptr %[[ARGTY_SIZE_PTR]] -// CHECK: %[[ARGTY_SIZE2:.*]] = add i64 %[[ARGTY_ALIGN4]], %[[ARGTY_SIZE1]] -// CHECK: %[[ARGTY_ALIGN5:.*]] = or i64 7, %[[ARGTY_ALIGN1]] -// CHECK: %[[PA_BOX_ALLOC:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @{{.*}}, i32 0, i32 2), i64 %[[ARGTY_SIZE2]], i64 %[[ARGTY_ALIGN5]]) -// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_BOX_ALLOC]], i32 0, i32 1 +// 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]], i64 %[[ARGTY_ALIGN4]] +// 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]]) @@ -1414,9 +1507,10 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): // 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: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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]], i64 -1 +// 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 @@ -1425,19 +1519,19 @@ bb0(%a : $SwiftClass, %b : $*T, %c : $Int): // 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 -// CHECK: %[[SIZE:.*]] = load i64, ptr %[[WITNESS_SIZE]] -// CHECK: %[[PA_CTX2:.*]] = getelementptr inbounds i8, ptr %[[PA_CTX_BOX]], i64 %{{.*}} -// CHECK: %[[ARG_COPY:.*]] = call ptr @malloc(i64 %[[SIZE]]) +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @captured_dependent_out_param(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr %[[INDIRECT_RET]], ptr noalias %[[ARG_COPY]], 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]], align 8 +// 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 @@ -1456,16 +1550,20 @@ bb0(%x : $*T): return %p : $@yield_once @callee_guaranteed @substituted () -> (@out T, @yields @in T) for } + // 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: %[[PA_ARG1:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3 +// 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: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 4 +// 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 @@ -1480,15 +1578,18 @@ bb0(%x : $*T): // CHECK: %[[SPILL:.*]] = call ptr @malloc // CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$sTA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: %[[PA_ARG1:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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: %[[PA_ARG_FUNC_SELF:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 3 +// 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: %[[PA_ARG_FUNC:.*]] = getelementptr inbounds <{ %swift.refcounted, %Ts5Int32V, [4 x i8], ptr, ptr }>, ptr %[[PA_CTX_BOX]], i32 0, i32 4 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// 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 @@ -1533,20 +1634,22 @@ sil_vtable Sub {} sil public_external @receive_closure : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed () -> (@owned C, @yields C)) -> () sil public_external @receive_closure2 : $@yield_once @convention(thin) (@owned @yield_once @callee_guaranteed (@guaranteed Base) -> (@owned C, @yields C)) -> () -// CHECK: define {{.*}} { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr %[[ARG0:.*]], ptr %[[ARG1:.*]]) +// 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]], align 8 +// 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: define {{.*}} ptr @parametric_casting_closure.resume.0(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// CHECK: %[[RET:.*]] = load ptr, ptr %[[FRAME]] // CHECK: %[[RET_SEL:.*]] = select i1 %[[UNWIND]], ptr undef, ptr %[[RET]] // CHECK: ret ptr %[[RET_SEL]] // CHECK: } @@ -1566,104 +1669,107 @@ bb2: // CHECK-LABEL: define{{.*}} swiftcc void @test_partial_apply // CHECK-SAME: (ptr %[[ARG0:.*]]) // CHECK: entry: -// CHECK: %[[CTX0:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[CTX1:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[CTX0PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX0]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX0PTR]]) -// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa"(i64 0) +// 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(32) %[[CTX0PTR]], ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}{{.*}}", ptr %[[ARG0]], ptr %[[MD]]) -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0PTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX0PTR]]) -// CHECK: %[[CTX1PTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX1]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTX1PTR]]) -// CHECK: %[[RESUME1:.*]] = call swiftcc ptr @receive_closure2(ptr noalias dereferenceable(32) %[[CTX1PTR]], ptr @"$s26parametric_casting_closureTA{{.*}}", ptr null, ptr %[[MD]]) -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1PTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTX1PTR]]) +// 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(32) %[[CTX:.*]], ptr %1, ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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"(i64 0) +// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa" // CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %1, ptr %[[MD]]) +// 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]], align 8 +// 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: define {{.*}} ptr @"$s26parametric_casting_closureTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: define {{.*}} { ptr, ptr } @"$s26parametric_casting_closureTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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"(i64 0) +// CHECK: %[[MDRESP:.*]] = call swiftcc %swift.metadata_response @"$s18partial_apply_coro3SubCMa" // CHECK: %[[MD:.*]] = extractvalue %swift.metadata_response %[[MDRESP]], 0 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @parametric_casting_closure(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr %[[PA_CTX_BOX]], ptr %[[MD]]) +// 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]], align 8 +// 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: define {{.*}} ptr @"$s26parametric_casting_closureTA.{{[0-9]+}}.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %{{.*}} = call swiftcc ptr %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: %[[RET:.*]] = call swiftcc ptr %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1687,31 +1793,34 @@ bb0(%0 : $Base): 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: (i64 %[[ARG:.*]], ptr %[[TY1:.*]], ptr %[[TY2:.*]], ptr %[[TY3:.*]]) +// CHECK-SAME: ([[ARG_TYPE:(i32|i64)]] %[[ARG:.*]], ptr %[[TY1:.*]], ptr %[[TY2:.*]], ptr %[[TY3:.*]]) // CHECK: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8] +// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8] // CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}} -// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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: %[[PA_ARG:.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// 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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// 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 32, ptr %[[CTXPTR]]) +// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]]) // CHECK: ret void // CHECK: } @@ -1719,21 +1828,23 @@ protocol P2 { associatedtype Y : P1 } // CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) // CHECK: entry: // CHECK: %[[SPILL:.*]] = call ptr @malloc -// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s24complex_generic_functionTA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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: %[[PA_ARG_PTR:.*]] = getelementptr inbounds <{ %swift.refcounted, [24 x i8], %TSi }>, ptr %[[PA_CTX_BOX]], i32 0, i32 2 +// 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 i64, ptr %[[PA_ARG]] +// CHECK: %[[ARG:.*]] = load [[ARG_TYPE]], ptr %[[PA_ARG]] // CHECK: call void @swift_release(ptr %[[PA_CTX_BOX]]) -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @complex_generic_function(ptr noalias {{.*}} %[[FRAMEPTR]], i64 %[[ARG]], ptr %[[TY1]], ptr %[[TY2]], ptr %[[TY3]]) +// 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]] @@ -1755,36 +1866,38 @@ bb0(%0 : $Int): return %result : $() } -// CHECK: define {{.*}} void @partial_apply_with_generic_type +// CHECK-LABEL: define {{.*}} void @partial_apply_with_generic_type // CHECK-SAME: (ptr %[[TY1:.*]], ptr %[[TY2:.*]]) // CHECK: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8] +// CHECK: %[[CTX:.*]] = alloca [[[BUFFER_SIZE]] x i8] // CHECK: %[[PA_CTX_BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, {{.*}}) -// CHECK: %[[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"(i64 0, ptr %[[TY1]], ptr %[[TY2]]) +// 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 [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) +// 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 32, ptr %[[CTXPTR]]) +// CHECK: call void @llvm.lifetime.end.p0(i64 [[BUFFER_SIZE]], ptr %[[CTXPTR]]) // CHECK: ret void // CHECK: } -// CHECK: define {{.*}} { ptr, ptr } @"$s16generic_functionTA" +// 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: %[[PA_CTX:.*]] = getelementptr inbounds <{ %swift.refcounted, [8 x i8] }>, ptr %[[PA_CTX_BOX]], i32 0, i32 1 +// 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]]) #3 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// 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 @@ -1807,7 +1920,6 @@ bb0: return %result : $() } - // Crash on partial apply of a generic enum. enum GenericEnum { case X(String) @@ -1820,13 +1932,13 @@ entry(%i : $Int): unreachable } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return -// CHECK-SAME: (i64 %[[ARG:.*]]) +// 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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] +// 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: } @@ -1849,13 +1961,13 @@ entry(%i : $Int): unreachable } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_generic_indirect_return2 -// CHECK-SAME: (i64 %[[ARG:.*]]) +// 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 i64 %[[ARG]], ptr %[[PA_ARG_PTR]] +// 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: } @@ -1869,55 +1981,59 @@ sil @partial_apply_generic_indirect_return2 : $@convention(thin) (Int) -> @yield struct SwiftStruct {} -// CHECK: define {{.*}} { ptr, ptr } @fun(ptr noalias dereferenceable(32) %0, ptr %1) +// 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: define{{.*}} swiftcc { ptr, ptr } @partial_apply_thin_type(ptr %[[ARG:.*]]) +// 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: define {{.*}} { ptr, ptr } @"$s3funTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr } @fun(ptr noalias dereferenceable(32) %[[FRAMEPTR]], 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 } @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]], align 8 +// 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: define {{.*}} void @"$s3funTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// CHECK-LABEL: unwind: // CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// CHECK-LABEL: resume: // CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s3funTA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -1929,6 +2045,7 @@ entry(%0: $@thin SwiftStruct.Type, %1: $SwiftClass): return %closure : $@yield_once @callee_guaranteed () -> (@yields SwiftStruct, @yields SwiftClass) } + struct A1 { let b: () -> () } @@ -1941,65 +2058,69 @@ class A3 {} sil_vtable A3 {} -// CHECK: define {{.*}} { ptr, ptr, ptr } @amethod(ptr noalias dereferenceable(32) %0, ptr noalias nocapture swiftself dereferenceable(8) %1, ptr noalias nocapture swifterror dereferenceable(8) %2) +// CHECK-LABEL: define {{.*}} { ptr, ptr, ptr } @amethod +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:(16|32)]]) %0, ptr noalias nocapture swiftself dereferenceable([[SELF_SIZE:(4|8)]]) %1, ptr noalias nocapture swifterror dereferenceable([[ERROR_SIZE:(4|8)]]) %2) sil @amethod : $@yield_once @convention(method) (@in_guaranteed A2) -> (@yields A1, @error Error) { entry(%a : $*A2): %0 = builtin "int_trap"() : $Never unreachable } -// CHECK: define {{.*}} { ptr, ptr } @repo(ptr noalias nocapture dereferenceable(8) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @repo +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[SELF_SIZE]]) %[[ARG:.*]]) // CHECK: %[[RET:.*]] = insertvalue { ptr, ptr } { ptr @"$s7amethodTA{{.*}}", ptr undef }, ptr %{{.*}}, 1 // CHECK: ret { ptr, ptr } %[[RET]] // CHECK: } // -// CHECK: define {{.*}} { ptr, ptr, ptr } @"$s7amethodTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], ptr swiftself %[[SELF:.*]], ptr noalias nocapture swifterror dereferenceable(8) %[[ERRORPTR:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr, ptr } @"$s7amethodTA" +// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]) %[[CTX:.*]], ptr swiftself %[[SELF:.*]], ptr noalias nocapture swifterror dereferenceable([[ERROR_SIZE]]) %[[ERRORPTR:.*]]) // CHECK: entry: -// CHECK: %[[SELFPTR:.*]] = alloca ptr, align 8 +// CHECK: %[[SELFPTR:.*]] = alloca ptr // CHECK: %[[SPILL:.*]] = call ptr @malloc -// CHECK: store ptr %[[SPILL]], ptr %[[CTX]], align 8 +// CHECK: store ptr %[[SPILL]], ptr %[[CTX]] // CHECK: %[[FRAME:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[SPILL]], i32 0, i32 0 -// CHECK: store ptr %[[SELF]], ptr %[[SELFPTR]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: store ptr null, ptr %[[ERRORPTR]], align 8 -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, ptr, ptr } @amethod(ptr noalias dereferenceable(32) %[[FRAMEPTR]], ptr noalias nocapture swiftself dereferenceable(8) %[[SELFPTR]], ptr noalias nocapture swifterror dereferenceable(8) %[[ERRORPTR]]) -// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]], align 8 +// 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 nocapture swiftself dereferenceable([[SELF_SIZE]]) %[[SELFPTR]], ptr noalias nocapture swifterror 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]], align 8 +// 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]], align 8 +// 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: define {{.*}} void @"$s7amethodTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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, align 8 -// CHECK: %[[FRAME:.*]] = load ptr, ptr %[[CTX]], align 8 +// 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]], align 8 +// CHECK: %[[ERRORVAL:.*]] = load ptr, ptr %[[ERRORPTR]] // CHECK: br i1 %[[UNWIND]], label %unwind, label %resume // -// CHECK: unwind: +// CHECK-LABEL: unwind: // CHECK: %[[RESUME_ADDR0:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME0:.*]] = load ptr, ptr %[[RESUME_ADDR0]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) -// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]], align 8 +// 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: resume: +// CHECK-LABEL: resume: // CHECK: %[[RESUME_ADDR1:.*]] = getelementptr inbounds %"$s7amethodTA.Frame", ptr %[[FRAME]], i32 0, i32 1 -// CHECK: %[[RESUME1:.*]] = load ptr, ptr %[[RESUME_ADDR1]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) -// CHECK: store ptr %[[ERRORVAL]], ptr %[[ERRORPTR]], align 8 +// 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: } @@ -2015,52 +2136,56 @@ bb0(%0 : $*A2): return %5 : $@yield_once @callee_guaranteed () -> (@yields A1, @error Error) } -// CHECK: define {{.*}} { ptr, ptr } @partial_apply_callee_guaranteed_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} { ptr, ptr } @partial_apply_callee_guaranteed_indirect_guaranteed_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[ARG_SIZE:(8|16)]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[BOX:.*]] = call noalias ptr @swift_allocObject(ptr getelementptr inbounds (%swift.full_boxmetadata, ptr @metadata.{{.*}}, i32 0, i32 2), i64 32, i64 7) +// 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.i64(ptr align 8 %[[BOXPTR]], ptr align 8 %[[ARG]], i64 16, i1 false) +// 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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 [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[PA_ARG]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[PA_ARG]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_CTX]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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 nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -2072,62 +2197,67 @@ bb0(%x : $*SwiftClassPair): 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: define {{.*}} @partial_apply_stack_callee_guaranteed_indirect_guaranteed_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} @partial_apply_stack_callee_guaranteed_indirect_guaranteed_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[ARG_SIZE:(8|16)]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// 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]], align 8 -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}{{.*}}", ptr %[[BOX]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: define {{.*}} { ptr, i64 } @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_guaranteed_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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 nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s45indirect_guaranteed_captured_class_pair_paramTA.{{[0-9]+}}.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -2144,68 +2274,74 @@ bb0(%x : $*SwiftClassPair): return %t : $() } -// CHECK: define {{.*}} { ptr, i64 } @indirect_in_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %{{.*}}, ptr noalias nocapture dereferenceable(16) %{{.*}}) +// 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 nocapture 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: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// 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]], align 8 -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s37indirect_in_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: define {{.*}} { ptr, i64 } @"$s37indirect_in_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_in_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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 nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s37indirect_in_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @"$s37indirect_in_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -2226,17 +2362,12 @@ bb0(%x : $*SwiftClassPair): // 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]], i64 -1 +// 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 -// CHECK: [[FLAGS:%.*]] = load i32, ptr [[FLAGS_PTR]] -// CHECK: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 -// CHECK: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 -// CHECK: = xor i64 [[ALIGNMASK]], -1 -// CHECK: = add i64 16, [[ALIGNMASK]] 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) -> () { @@ -2344,68 +2475,74 @@ entry: return %t : $() } -// CHECK: define {{.*}} { ptr, i64 } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable(32) %0, i64 %1, ptr noalias nocapture dereferenceable(16) %2) +// 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 nocapture 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: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_constant_class_pair_param(ptr noalias nocapture dereferenceable(16) %[[ARG:.*]]) +// CHECK-LABEL: define {{.*}} void @partial_apply_stack_callee_guaranteed_indirect_in_constant_class_pair_param +// CHECK-SAME: (ptr noalias nocapture dereferenceable([[PAIR_SIZE]]) %[[ARG:.*]]) // CHECK: entry: -// CHECK: %[[CTX:.*]] = alloca [32 x i8], align 8 -// CHECK: %[[BOX:.*]] = alloca i8, i64 24, align 16 +// 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]], align 8 -// CHECK: %[[CTXPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[CTX]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[CTXPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @use_closure2(ptr noalias dereferenceable(32) %[[CTXPTR]], ptr @"$s46indirect_in_constant_captured_class_pair_paramTA{{.*}}", ptr %[[BOX]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: call swiftcc void %[[RESUME]](ptr noalias dereferenceable(32) %[[CTXPTR]], i1 false) -// CHECK: call void @llvm.lifetime.end.p0(i64 32, ptr %[[CTXPTR]]) +// 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: define {{.*}} { ptr, i64 } @"$s46indirect_in_constant_captured_class_pair_paramTA"(ptr noalias dereferenceable(32) %[[CTX:.*]], i64 %[[ARG0:.*]], ptr swiftself %[[PA_CTX_BOX:.*]]) +// 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]], align 8 +// 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]], align 8 -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) -// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc { ptr, i64 } @indirect_in_constant_captured_class_pair_param(ptr noalias dereferenceable(32) %[[FRAMEPTR]], i64 %[[ARG0]], ptr noalias nocapture dereferenceable(16) %[[PA_ARG]]) -// CHECK: %[[RESUME:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 0 +// 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 nocapture 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]], align 8 -// CHECK: %[[YIELD:.*]] = extractvalue { ptr, i64 } %[[YIELD_PAIR]], 1 -// CHECK: %[[RET0:.*]] = insertvalue { ptr, i64 } poison, ptr @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0", 0 -// CHECK: %[[RET1:.*]] = insertvalue { ptr, i64 } %[[RET0]], i64 %[[YIELD]], 1 -// CHECK: ret { ptr, i64 } %[[RET1]] +// 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: define {{.*}} void @"$s46indirect_in_constant_captured_class_pair_paramTA.resume.0"(ptr noalias noundef nonnull align 8 dereferenceable(32) %[[CTX:.*]], i1 %[[UNWIND:.*]]) +// 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]], align 8 +// 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: unwind: +// 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]], align 8 -// CHECK: %[[CTX0:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME0]](ptr noalias dereferenceable(32) %[[CTX0]], i1 true) +// 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: resume: +// 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]], align 8 -// CHECK: %[[CTX1:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAMEPTR]], i32 0, i32 0 -// CHECK: call swiftcc void %[[RESUME1]](ptr noalias dereferenceable(32) %[[CTX1]], i1 false) +// 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: } @@ -2431,29 +2568,29 @@ bb0(%thick : $@callee_guaranteed @yield_once @convention(thick) (Int64, Int32) - } // CHECK-LABEL: define {{.*}} { ptr, ptr } @dont_crash -// CHECK-SAME: (i64 %[[ARG:.*]]) +// 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 i64 %[[ARG]], ptr %[[ARGPTR]] +// 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:.*]], i64 %[[ARG1:.*]], ptr swiftself %[[PA_CTX_BOX:.*]], ptr noalias nocapture swifterror {{.*}} %[[ERROR:.*]]) +// CHECK-SAME: (ptr noalias {{.*}} %[[CTX:.*]], [[ARG_TYPE]] %[[ARG1:.*]], ptr swiftself %[[PA_CTX_BOX:.*]], ptr noalias nocapture swifterror {{.*}} %[[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 i64, ptr %[[PA_ARG]] -// CHECK: %[[FRAMEPTR:.*]] = getelementptr inbounds [32 x i8], ptr %[[FRAME]], i32 0, i32 0 -// CHECK: call void @llvm.lifetime.start.p0(i64 32, ptr %[[FRAMEPTR]]) +// 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]], i64 %[[ARG1]], i64 %[[ARG2]], ptr swiftself undef, ptr noalias nocapture swifterror {{.*}} %[[ERROR]]) +// CHECK: %[[YIELD_PAIR:.*]] = call swiftcc ptr @external_closure(ptr noalias {{.*}} %[[FRAMEPTR]], [[ARG_TYPE]] %[[ARG1]], [[ARG_TYPE]] %[[ARG2]], ptr swiftself undef, ptr noalias nocapture swifterror {{.*}} %[[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]] From f965df2d07ac8e6bb5df1e1f12598e89b44ee0d5 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Thu, 8 Aug 2024 11:43:45 -0700 Subject: [PATCH 12/12] Bring mangling of coroutine continuations back. Co-authored-by: Arnold Schwaighofer --- lib/IRGen/GenFunc.cpp | 5 ++++- lib/IRGen/IRGenMangler.h | 4 ++++ lib/IRGen/Linking.cpp | 6 ++---- test/IRGen/yield_once.sil | 7 +++---- test/IRGen/yield_once_big.sil | 14 ++++++-------- test/IRGen/yield_once_biggish.sil | 7 +++---- test/IRGen/yield_once_indirect.sil | 7 +++---- test/IRGen/yield_result.sil | 11 +++++------ 8 files changed, 30 insertions(+), 31 deletions(-) diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 32cc0216203d2..6b5b2a121a414 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1456,8 +1456,11 @@ class CoroPartialApplicationForwarderEmission Self(nullptr), FirstData(nullptr), SecondData(nullptr) {} void begin() override { + auto unsubstType = substType->getUnsubstitutedType(IGM.getSILModule()); auto prototype = subIGF.IGM.getOpaquePtr( - subIGF.IGM.getAddrOfContinuationPrototype(origType)); + subIGF.IGM.getAddrOfContinuationPrototype( + cast( + unsubstType->mapTypeOutOfContext()->getCanonicalType()))); // Use malloc and free as our allocator. auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn()); diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h index ac646a451a3b5..d777686673ed7 100644 --- a/lib/IRGen/IRGenMangler.h +++ b/lib/IRGen/IRGenMangler.h @@ -498,6 +498,10 @@ class IRGenMangler : public Mangle::ASTMangler { CanType shapeType, bool isUnique); + std::string mangleCoroutineContinuationPrototype(CanSILFunctionType type) { + return mangleTypeSymbol(type, "TC"); + } + std::string mangleReflectionBuiltinDescriptor(Type type) { const char * const reflectionDescriptorOp = "MB"; if (type->isAnyObject()) { diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp index 23306d8b90808..416105ce056f5 100644 --- a/lib/IRGen/Linking.cpp +++ b/lib/IRGen/Linking.cpp @@ -376,10 +376,8 @@ std::string LinkEntity::mangleAsString() const { } case Kind::CoroutineContinuationPrototype: - // Emit unnamed functions for coroutine continuation - // prototypes. These are supposed to be replaced by the LLVM - // coroutine lowering pass. - return std::string(); + return mangler.mangleCoroutineContinuationPrototype( + cast(getType())); // An Objective-C class reference reference. The symbol is private, so // the mangling is unimportant; it should just be readable in LLVM IR. diff --git a/test/IRGen/yield_once.sil b/test/IRGen/yield_once.sil index dfa5dad46f94c..f3282a6ef4e76 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: call swiftcc void @marker(i32 1000) @@ -43,8 +43,7 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc -// CHECK-SAME: void @[[CONT_FN]] +// 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) diff --git a/test/IRGen/yield_once_big.sil b/test/IRGen/yield_once_big.sil index 60158503840a6..8090e887a6320 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 @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr @@ -89,8 +89,7 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} -// CHECK-SAME: swiftcc void @[[CONT_FN]] +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) @@ -182,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 @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr @@ -238,6 +237,5 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} -// CHECK-SAME: swiftcc void @[[CONT_FN]] +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) diff --git a/test/IRGen/yield_once_biggish.sil b/test/IRGen/yield_once_biggish.sil index 0c3bf53ee697e..72e09248f110f 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 @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr // CHECK-NEXT: call swiftcc void @marker(i32 1000) @@ -93,8 +93,7 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} -// CHECK-SAME: swiftcc void @[[CONT_FN:[0-9]+]] +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) diff --git a/test/IRGen/yield_once_indirect.sil b/test/IRGen/yield_once_indirect.sil index 871556e0e6fc2..28af3ed2389c7 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 @[[CONT_FN:[0-9]+]], 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null) // CHECK-NEXT: store ptr // CHECK-NEXT: call swiftcc void @marker(i32 1000) @@ -80,8 +80,7 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} -// CHECK-SAME: swiftcc void @[[CONT_FN]] +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc void @"$s19yield_once_indirect8IndirectVyxGAA9SomeClassCRbzlIetAYi_TC" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_simple_call(i1 %0) diff --git a/test/IRGen/yield_result.sil b/test/IRGen/yield_result.sil index 2361aeaa75693..1d380d620948a 100644 --- a/test/IRGen/yield_result.sil +++ b/test/IRGen/yield_result.sil @@ -13,8 +13,8 @@ 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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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-NEXT: call swiftcc void @marker(i64 1000) @@ -47,8 +47,7 @@ unwind: // CHECK-NEXT: unreachable } -// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} -// CHECK-SAME: swiftcc i64 @[[CONT_FN]] +// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc i64 @"$sBi64_IetAd_TC{{(.ptrauth)?}}" // CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1) // CHECK-LABEL: test_coro_ret @@ -99,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 @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) - // CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr [[CTX]], ptr @[[CONT_FN:[0-9]+]], ptr @malloc, ptr @free) + // 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: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[ARG]]) // CHECK: br i1 [[IS_UNWIND]], label %[[UNWIND_BB:.*]], label %[[RESUME_BB:.*]]