[thunk-lowering] Add a pass that performs lowering of ThunkInsts.

Right now it just handles the "identity" case so we can validate the
functionality.
This commit is contained in:
Michael Gottesman
2024-09-23 20:24:56 -07:00
parent 561662d6cc
commit f985b0ee03
7 changed files with 1362 additions and 0 deletions

View File

@@ -644,6 +644,13 @@ public:
return {functions.begin(), functions.end()};
}
/// Move \p fn to be in the function list before \p moveBefore.
void moveBefore(SILModule::iterator moveBefore, SILFunction *fn);
/// Move \p fn to be in the function list after \p moveAfter. It is assumed
/// that \p moveAfter is not end.
void moveAfter(SILModule::iterator moveAfter, SILFunction *fn);
const_iterator zombies_begin() const { return zombieFunctions.begin(); }
const_iterator zombies_end() const { return zombieFunctions.end(); }

View File

@@ -510,6 +510,8 @@ SWIFT_FUNCTION_PASS(UpdateBorrowedFrom, "update-borrowed-from",
"Test pass for update borrowed-from instructions")
PASS(DiagnoseUnnecessaryPreconcurrencyImports, "sil-diagnose-unnecessary-preconcurrency-imports",
"Diagnose any preconcurrency imports that Sema and TransferNonSendable did not use")
PASS(ThunkLowering, "sil-thunk-lowering",
"Lower thunk instructions to actual thunks")
PASS(PruneVTables, "prune-vtables",
"Mark class methods that do not require vtable dispatch")
PASS_RANGE(AllPasses, AliasInfoDumper, PruneVTables)

View File

@@ -940,6 +940,26 @@ void SILModule::performOnceForPrespecializedImportedExtensions(
prespecializedFunctionDeclsImported = true;
}
void SILModule::moveBefore(SILModule::iterator moveAfter, SILFunction *fn) {
assert(&fn->getModule() == this);
assert(&moveAfter->getModule() == this);
assert(moveAfter != end() &&
"We assume that moveAfter must not be end since nothing is after end");
getFunctionList().remove(fn->getIterator());
getFunctionList().insert(moveAfter, fn);
}
void SILModule::moveAfter(SILModule::iterator moveAfter, SILFunction *fn) {
assert(&fn->getModule() == this);
assert(&moveAfter->getModule() == this);
assert(moveAfter != end() &&
"We assume that moveAfter must not be end since nothing is after end");
getFunctionList().remove(fn->getIterator());
getFunctionList().insertAfter(moveAfter, fn);
}
SILProperty *
SILProperty::create(SILModule &M, unsigned Serialized, AbstractStorageDecl *Decl,
std::optional<KeyPathPatternComponent> Component) {

View File

@@ -44,6 +44,7 @@ target_sources(swiftSILOptimizer PRIVATE
PMOMemoryUseCollector.cpp
RawSILInstLowering.cpp
ReferenceBindingTransform.cpp
ThunkLowering.cpp
TransferNonSendable.cpp
LowerTupleAddrConstructor.cpp
SILGenCleanup.cpp

View File

@@ -0,0 +1,410 @@
//===--- ThunkLowering.cpp ------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/Defer.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// MARK: Utilities
//===----------------------------------------------------------------------===//
static CanSILFunctionType
getThunkFunctionType(ThunkInst::Kind kind, CanSILFunctionType inputFunctionType,
SILModule &mod) {
switch (kind) {
case ThunkInst::Kind::Invalid:
return CanSILFunctionType();
case ThunkInst::Kind::Identity: {
// Our thunk type is a thin function that takes the input function type and
// the input function type's parameters.
llvm::SmallVector<SILParameterInfo, 8> newParameters;
for (SILParameterInfo p : inputFunctionType->getParameters()) {
newParameters.push_back(p);
}
newParameters.push_back(SILParameterInfo(
inputFunctionType, ParameterConvention::Direct_Guaranteed));
SILExtInfoBuilder builder;
builder = builder.withRepresentation(SILFunctionTypeRepresentation::Thin)
.withAsync(inputFunctionType->isAsync());
return SILFunctionType::get(
inputFunctionType->getInvocationGenericSignature(), builder.build(),
inputFunctionType->getCoroutineKind(),
ParameterConvention::Direct_Unowned, newParameters,
inputFunctionType->getYields(), inputFunctionType->getResults(),
inputFunctionType->getOptionalErrorResult(),
inputFunctionType->getPatternSubstitutions(),
inputFunctionType->getInvocationSubstitutions(),
inputFunctionType->getASTContext());
}
}
llvm_unreachable("Covered switch isn't covered?!");
}
namespace {
struct ThunkBodyBuilder {
SILBuilder builder;
SILFunction *thunk;
llvm::SmallVector<SILValue, 8> thunkArguments;
/// We always prepare the first block so we can have the builder setup.
ThunkBodyBuilder(SILFunction *thunk)
: builder(thunk->createBasicBlock()), thunk(thunk) {}
/// Default implementation. Just forwards the arguments. Intended to be used
/// as an example for other more complex generates by builders that compose
/// with ThunkBodyBuilder.
void generate();
/// Return a loc for our thunks. Is autogenerated so it doesnt show up in
/// debug info. Just to make it quicker to type.
SILLocation getLoc() const {
return RegularLocation::getAutoGeneratedLocation();
}
CanSILFunctionType getThunkType() const {
return thunk->getLoweredFunctionType();
}
SILFunctionConventions getThunkConventions() const {
return SILFunctionConventions(getThunkType(), thunk->getModule());
}
/// Create the entry block arguments for the function.
void createEntryBlockArguments();
/// Create a call to the thunked function.
void callThunkedFunction(SILValue function, ArrayRef<SILValue> arguments);
private:
void callApplyThunkedFunction(SILValue function,
ArrayRef<SILValue> arguments);
void callTryApplyThunkedFunction(SILValue function,
ArrayRef<SILValue> arguments);
void callBeginApplyThunkedFunction(SILValue function,
ArrayRef<SILValue> arguments);
};
} // namespace
void ThunkBodyBuilder::createEntryBlockArguments() {
auto conventions = getThunkConventions();
auto *block = &thunk->front();
assert(block->getNumArguments() == 0 && "entry should be uninitialized");
// First add our indirect results.
for (auto indirectResult : conventions.getIndirectSILResults()) {
SILType ty = conventions.getSILType(indirectResult,
thunk->getTypeExpansionContext());
ty = thunk->mapTypeIntoContext(ty);
thunkArguments.push_back(block->createFunctionArgument(ty));
}
// Then add our normal parameters.
for (auto paramInfo : conventions.getParameters()) {
SILType ty =
conventions.getSILType(paramInfo, thunk->getTypeExpansionContext());
ty = thunk->mapTypeIntoContext(ty);
thunkArguments.push_back(block->createFunctionArgument(ty));
}
}
void ThunkBodyBuilder::callApplyThunkedFunction(SILValue function,
ArrayRef<SILValue> arguments) {
auto *ai =
builder.createApply(RegularLocation::getAutoGeneratedLocation(), function,
thunk->getForwardingSubstitutionMap(), arguments);
builder.createReturn(RegularLocation::getAutoGeneratedLocation(), ai);
}
void ThunkBodyBuilder::callBeginApplyThunkedFunction(
SILValue function, ArrayRef<SILValue> arguments) {
auto *ai = builder.createBeginApply(
RegularLocation::getAutoGeneratedLocation(), function,
thunk->getForwardingSubstitutionMap(), arguments);
auto *resumeBlock = thunk->createBasicBlock();
{
auto conventions = getThunkConventions();
SILBuilder resumeBlockBuilder(resumeBlock);
llvm::SmallVector<TupleTypeElt> directResultTypes;
for (auto result : conventions.getDirectSILResults()) {
auto ty =
conventions.getSILType(result, thunk->getTypeExpansionContext());
ty = thunk->mapTypeIntoContext(ty);
directResultTypes.push_back(ty.getASTType());
}
SILType resultType = SILType::getEmptyTupleType(thunk->getASTContext());
if (directResultTypes.size() == 1) {
resultType = SILType::getPrimitiveObjectType(
directResultTypes.front().getType()->getCanonicalType());
} else if (directResultTypes.size() > 1) {
auto tupleTy = TupleType::get(directResultTypes, thunk->getASTContext())
->getCanonicalType();
resultType = SILType::getPrimitiveObjectType(tupleTy);
}
SILValue result = resumeBlockBuilder.createEndApply(
getLoc(), ai->getTokenResult(), resultType);
resumeBlockBuilder.createReturn(getLoc(), result);
}
auto *unwindBlock = thunk->createBasicBlock();
{
SILBuilder unwindBlockBuilder(unwindBlock);
unwindBlockBuilder.createAbortApply(getLoc(), ai->getTokenResult());
unwindBlockBuilder.createUnwind(getLoc());
}
// Then return the result of applying the method.
llvm::SmallVector<SILValue, 8> yieldedValues;
copy(ai->getYieldedValues(), std::back_inserter(yieldedValues));
builder.createYield(RegularLocation::getAutoGeneratedLocation(),
yieldedValues, resumeBlock, unwindBlock);
}
void ThunkBodyBuilder::callTryApplyThunkedFunction(
SILValue function, ArrayRef<SILValue> arguments) {
// Then handle the try_apply case.
auto conventions = getThunkConventions();
// Create our normal block.
auto *normalBlock = thunk->createBasicBlock();
{
// Create the argument for our direct results.
llvm::SmallVector<TupleTypeElt, 8> normalBlockArgs;
for (auto result : conventions.getDirectSILResults()) {
auto ty =
conventions.getSILType(result, thunk->getTypeExpansionContext());
ty = thunk->mapTypeIntoContext(ty);
normalBlockArgs.push_back(ty.getASTType());
}
SILValue resultValue;
if (normalBlockArgs.empty()) {
// If our normal block args is empty, generate an empty tuple typed
// argument since SIL requires at least one argument.
resultValue = normalBlock->createPhiArgument(
SILType::getEmptyTupleType(thunk->getASTContext()),
OwnershipKind::None);
} else if (normalBlockArgs.size() == 1) {
// If we have a single direct result, just emit a phi argument directly of
// that type.
resultValue = normalBlock->createPhiArgument(
SILType::getPrimitiveObjectType(
normalBlockArgs.front().getType()->getCanonicalType()),
OwnershipKind::Owned);
} else {
// Otherwise, create a tuple type and one single phi argument for all of
// our values.
auto tupleType = TupleType::get(normalBlockArgs, thunk->getASTContext())
->getCanonicalType();
resultValue = normalBlock->createPhiArgument(
SILType::getPrimitiveObjectType(tupleType), OwnershipKind::Owned);
}
assert(resultValue);
SILBuilder normalBlockBuilder(normalBlock);
normalBlockBuilder.createReturn(getLoc(), resultValue);
}
// Then create our error block.
auto *errorBlock = thunk->createBasicBlock();
{
auto errorArg = errorBlock->createPhiArgument(
SILType::getExceptionType(thunk->getASTContext()),
OwnershipKind::Owned);
SILBuilder errorBlockBuilder(errorBlock);
errorBlockBuilder.createThrow(getLoc(), errorArg);
}
// Finally wire up the try apply.
builder.createTryApply(RegularLocation::getAutoGeneratedLocation(), function,
thunk->getForwardingSubstitutionMap(), arguments,
normalBlock, errorBlock);
}
void ThunkBodyBuilder::callThunkedFunction(SILValue function,
ArrayRef<SILValue> arguments) {
auto thunkType = getThunkType();
// First see if we have a coroutine.
if (thunkType->getCoroutineKind() == SILCoroutineKind::YieldOnce) {
return callBeginApplyThunkedFunction(function, arguments);
}
// Then see if we have a normal apply.
if (!thunkType->hasErrorResult()) {
return callApplyThunkedFunction(function, arguments);
}
// Finally handle try_apply.
return callTryApplyThunkedFunction(function, arguments);
}
void ThunkBodyBuilder::generate() {
createEntryBlockArguments();
callThunkedFunction(thunkArguments.back(),
ArrayRef<SILValue>(thunkArguments).drop_back());
}
//===----------------------------------------------------------------------===//
// MARK: Identity
//===----------------------------------------------------------------------===//
namespace {
struct IdentityLowering {
SILOptFunctionBuilder &funcBuilder;
ThunkInst *ti;
// The number of thunks emitted into the function. Just an easy way to give
// multiple thunks in a function a unique name for prototyping purposes.
unsigned &thunkCount;
IdentityLowering(SILOptFunctionBuilder &funcBuilder, ThunkInst *ti,
unsigned &thunkCount)
: funcBuilder(funcBuilder), ti(ti), thunkCount(thunkCount) {}
void lower() &&;
void invalidate() {
ti->eraseFromParent();
ti = nullptr;
};
~IdentityLowering() {
assert(!ti && "Did not call consuming method to destroy value");
}
SILFunction *createThunk() const;
};
} // namespace
void IdentityLowering::lower() && {
SWIFT_DEFER { invalidate(); };
// Create the thunk.
auto *thunk = createThunk();
SILBuilderWithScope builder(ti);
SingleValueInstruction *thunkValue =
builder.createFunctionRef(ti->getLoc(), thunk);
thunkValue = builder.createPartialApply(
ti->getLoc(), thunkValue, ti->getSubstitutionMap(), ti->getOperand(),
ParameterConvention::Direct_Guaranteed);
ti->replaceAllUsesWith(thunkValue);
}
SILFunction *IdentityLowering::createThunk() const {
// Our type is going to be the result of the function.
auto inputFuncType = ti->getOperand()->getType().getAs<SILFunctionType>();
// We need to add our input type as a parameter and have our result type as
// the result of the function type.
GenericSignature genericSig;
auto thunkType =
getThunkFunctionType(ti->getThunkKind(), inputFuncType, ti->getModule());
// Just for prototyping
llvm::SmallString<64> name;
{
llvm::raw_svector_ostream os(name);
os << ti->getFunction()->getName() << "_identity_" << thunkCount;
++thunkCount;
}
auto *fn = funcBuilder.getOrCreateSharedFunction(
RegularLocation::getAutoGeneratedLocation(), name, thunkType,
IsBare_t::IsNotBare, IsTransparent_t::IsNotTransparent,
SerializedKind_t::IsNotSerialized, ProfileCounter(), IsThunk_t::IsThunk,
IsDynamicallyReplaceable_t::IsNotDynamic,
IsDistributed_t::IsNotDistributed,
IsRuntimeAccessible_t::IsNotRuntimeAccessible);
// These are only generated when not in Ownership SSA. Turn off Ownership SSA
// so that SILBuilder and other utilities do the right thing and so we can
// avoid having to run ownership lowering.
fn->setOwnershipEliminated();
// Set up our generic environment to be the same as our original function.
fn->setGenericEnvironment(ti->getFunction()->getGenericEnvironment());
// Move the thunk to be right before the generated function to ease FileCheck.
fn->getModule().moveBefore(ti->getFunction()->getIterator(), fn);
// Generate the body of the function.
ThunkBodyBuilder thunkBodyBuilder(fn);
thunkBodyBuilder.generate();
return fn;
}
//===----------------------------------------------------------------------===//
// MARK: Top Level Entrypoint
//===----------------------------------------------------------------------===//
namespace {
class ThunkLoweringPass : public SILFunctionTransform {
void run() override {
auto *fn = getFunction();
SILOptFunctionBuilder funcBuilder(*this);
// A per function thunk count that can be used to quickly generate unique
// per function names for thunks by appending the name of the thunk and a
// count to the function name. Increment this every time you create a thunk.
unsigned thunkCount = 0;
// It is assumed in this code that the only instruction we delete is the
// thunk itself. We leave cleaning everything else up to other passes just
// to make the invalidation rules in this pass simple.
for (auto &block : *fn) {
for (auto ii = block.begin(), ie = block.end(); ii != ie;) {
auto *ti = dyn_cast<ThunkInst>(&*ii);
++ii;
if (!ti)
continue;
switch (ti->getThunkKind()) {
case ThunkInst::Kind::Invalid:
llvm_unreachable("Should never see an invalid kind");
case ThunkInst::Kind::Identity:
IdentityLowering lowering(funcBuilder, ti, thunkCount);
std::move(lowering).lower();
continue;
}
llvm_unreachable("Covered switch isn't covered?!");
}
}
}
};
} // namespace
SILTransform *swift::createThunkLowering() { return new ThunkLoweringPass(); }

View File

@@ -915,6 +915,8 @@ SILPassPipelinePlan
SILPassPipelinePlan::getLoweringPassPipeline(const SILOptions &Options) {
SILPassPipelinePlan P(Options);
P.startPipeline("Lowering");
// Lower thunks.
P.addThunkLowering();
P.addLowerHopToActor(); // FIXME: earlier for more opportunities?
P.addOwnershipModelEliminator();
P.addAlwaysEmitConformanceMetadataPreservation();

View File

@@ -0,0 +1,920 @@
// RUN: %target-sil-opt -sil-thunk-lowering %s | %FileCheck %s
// REQUIRES: asserts
sil_stage lowered
import Swift
////////////////////////
// MARK: Declarations //
////////////////////////
class Klass {}
sil @noparam_noreturn_callee : $@convention(thin) () -> ()
sil @oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> ()
sil @twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> ()
sil @noparam_oneresult_callee : $@convention(thin) () -> @owned Klass
sil @oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> @owned Klass
sil @twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass
sil @generic_noparam_noreturn_callee : $@convention(thin) <T> () -> ()
sil @generic_oneparam_noreturn_callee : $@convention(thin) <T> (@in T) -> ()
sil @generic_twoparam_noreturn_callee : $@convention(thin) <T> (@in T, @in T) -> ()
sil @generic_noparam_oneresult_callee : $@convention(thin) <T> () -> @out T
sil @generic_oneparam_oneresult_callee : $@convention(thin) <T> (@in T) -> @out T
sil @generic_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> @out T
sil @generic_mixed_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass)
sil @generic_mixed_2_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass)
sil @throws_noparam_noreturn_callee : $@convention(thin) () -> @error Error
sil @throws_oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> @error Error
sil @throws_twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @error Error
sil @throws_noparam_oneresult_callee : $@convention(thin) () -> (@owned Klass, @error Error)
sil @throws_oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> (@owned Klass, @error Error)
sil @throws_twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error Error)
sil @throws_noparam_tworesult_callee : $@convention(thin) () -> (@owned Klass, @owned Klass, @error Error)
sil @throws_oneparam_tworesult_callee : $@convention(thin) (@owned Klass) -> (@owned Klass, @owned Klass, @error Error)
sil @throws_twoparam_tworesult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @owned Klass, @error Error)
sil @generic_throws_noparam_noreturn_callee : $@convention(thin) <T> () -> @error Error
sil @generic_throws_oneparam_noreturn_callee : $@convention(thin) <T> (@in T) -> @error Error
sil @generic_throws_twoparam_noreturn_callee : $@convention(thin) <T> (@in T, @in T) -> @error Error
sil @generic_throws_noparam_oneresult_callee : $@convention(thin) <T> () -> (@out T, @error Error)
sil @generic_throws_oneparam_oneresult_callee : $@convention(thin) <T> (@in T) -> (@out T, @error Error)
sil @generic_throws_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @error Error)
sil @generic_throws_twoparam_mixedresults_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass, @out T, @error Error)
sil @generic_throws_twoparam_mixedresults_2_callee : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass, @out T, @error Error)
sil @async_noparam_noreturn_callee : $@convention(thin) @async () -> ()
sil @yield_noparam_twoyield_callee : $@yield_once @convention(thin) () -> (@yields Klass, @yields Klass)
sil @generic_yield_noparam_twoyield_callee : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0)
sil @generic_yield_noparam_mixedyieldreturn_callee : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @owned Klass, @yields τ_0_0, @yields Klass, @out τ_0_0, @yields τ_0_0, @owned Klass)
/////////////////////////////////////
// MARK: Unique Function Name Test //
/////////////////////////////////////
// Make sure that we come up with unique names in each function (which we hack
// by just adding a counter).
//
// CHECK-LABEL: sil @double_thunk_test : $@convention(thin) () -> () {
// CHECK: [[FUNC:%.*]] = function_ref @noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @double_thunk_test_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]() :
// CHECK: [[THUNK:%.*]] = function_ref @double_thunk_test_identity_1 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'double_thunk_test'
sil @double_thunk_test : $@convention(thin) () -> () {
%0 = function_ref @noparam_noreturn_callee : $@convention(thin) () -> ()
%1 = thunk [identity] %0() : $@convention(thin) () -> ()
apply %1() : $@callee_guaranteed () -> ()
%2 = thunk [identity] %0() : $@convention(thin) () -> ()
apply %2() : $@callee_guaranteed () -> ()
%9999 = tuple ()
return %9999 : $()
}
/////////////////////////////////////////////
// MARK: Direct Loadable Types Apply Tests //
/////////////////////////////////////////////
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_noparam_noresult_identity_0 : $@convention(thin) (@guaranteed @convention(thin) () -> ()) -> () {
// CHECK:bb0([[ARG:%.*]] : $@convention(thin) () -> ()):
// CHECK: apply [[ARG]]() : $@convention(thin) () -> ()
// CHECK: } // end sil function 'thunk_lowering_noparam_noresult_identity_0'
// CHECK-LABEL: sil @thunk_lowering_noparam_noresult : $@convention(thin) () -> () {
// CHECK: [[FUNC:%.*]] = function_ref @noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_noparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_noparam_noresult'
sil @thunk_lowering_noparam_noresult : $@convention(thin) () -> () {
%0 = function_ref @noparam_noreturn_callee : $@convention(thin) () -> ()
%1 = thunk [identity] %0() : $@convention(thin) () -> ()
apply %1() : $@callee_guaranteed () -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_oneparam_noresult : $@convention(thin) (@owned Klass) -> () {
// CHECK: bb0([[ARG:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @oneparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_oneparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_oneparam_noresult'
sil @thunk_lowering_oneparam_noresult : $@convention(thin) (@owned Klass) -> () {
bb0(%arg : $Klass):
%0 = function_ref @oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> ()
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass) -> ()
apply %1(%arg) : $@callee_guaranteed (@owned Klass) -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_twoparam_noresult : $@convention(thin) (@owned Klass, @owned Klass) -> () {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @twoparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_twoparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_twoparam_noresult'
sil @thunk_lowering_twoparam_noresult : $@convention(thin) (@owned Klass, @owned Klass) -> () {
bb0(%arg : $Klass, %arg2 : $Klass):
%0 = function_ref @twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> ()
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass, @owned Klass) -> ()
apply %1(%arg, %arg2) : $@callee_guaranteed (@owned Klass, @owned Klass) -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_noparam_oneresult : $@convention(thin) () -> @owned Klass {
// CHECK: [[FUNC:%.*]] = function_ref @noparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_noparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: [[RESULT:%.*]] = apply [[THUNKED_FUNC]]() :
// CHECK: return [[RESULT]]
// CHECK: } // end sil function 'thunk_lowering_noparam_oneresult'
sil @thunk_lowering_noparam_oneresult : $@convention(thin) () -> @owned Klass {
%0 = function_ref @noparam_oneresult_callee : $@convention(thin) () -> @owned Klass
%1 = thunk [identity] %0() : $@convention(thin) () -> @owned Klass
%2 = apply %1() : $@callee_guaranteed () -> @owned Klass
return %2 : $Klass
}
// CHECK-LABEL: sil @thunk_lowering_oneparam_oneresult : $@convention(thin) (@owned Klass) -> @owned Klass {
// CHECK: bb0([[ARG:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @oneparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_oneparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: [[RESULT:%.*]] = apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: return [[RESULT]]
// CHECK: } // end sil function 'thunk_lowering_oneparam_oneresult'
sil @thunk_lowering_oneparam_oneresult : $@convention(thin) (@owned Klass) -> @owned Klass {
bb0(%arg : $Klass):
%0 = function_ref @oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> @owned Klass
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass) -> @owned Klass
%2 = apply %1(%arg) : $@callee_guaranteed (@owned Klass) -> @owned Klass
return %2 : $Klass
}
// CHECK-LABEL: sil @thunk_lowering_twoparam_oneresult : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_twoparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: [[RESULT:%.*]] = apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: return [[RESULT]]
// CHECK: } // end sil function 'thunk_lowering_twoparam_oneresult'
sil @thunk_lowering_twoparam_oneresult : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass {
bb0(%arg : $Klass, %arg2 : $Klass):
%0 = function_ref @twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass, @owned Klass) -> @owned Klass
%2 = apply %1(%arg, %arg2) : $@callee_guaranteed (@owned Klass, @owned Klass) -> @owned Klass
return %2 : $Klass
}
///////////////////////////////
// MARK: Generic Apply Tests //
///////////////////////////////
// CHECK-LABEL: sil @thunk_lowering_generic_noparam_noresult : $@convention(thin) <T> () -> () {
// CHECK: [[FUNC:%.*]] = function_ref @generic_noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_noparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_generic_noparam_noresult'
sil @thunk_lowering_generic_noparam_noresult : $@convention(thin) <T> () -> () {
%0 = function_ref @generic_noparam_noreturn_callee : $@convention(thin) <τ_0_0> () -> ()
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> () -> ()
apply %1() : $@callee_guaranteed () -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_oneparam_noresult : $@convention(thin) <T> (@in T) -> () {
// CHECK: bb0([[ARG:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_oneparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_oneparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_oneparam_noresult'
sil @thunk_lowering_generic_oneparam_noresult : $@convention(thin) <T> (@in T) -> () {
bb0(%arg : $*T):
%0 = function_ref @generic_oneparam_noreturn_callee : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
apply %1(%arg) : $@callee_guaranteed (@in T) -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_twoparam_noresult : $@convention(thin) <T> (@in T, @in T) -> () {
// CHECK: bb0([[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_twoparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_twoparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_twoparam_noresult'
sil @thunk_lowering_generic_twoparam_noresult : $@convention(thin) <T> (@in T, @in T) -> () {
bb0(%arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_twoparam_noreturn_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> ()
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> ()
apply %1(%arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> ()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_noparam_oneresult : $@convention(thin) <T> () -> @out T {
// CHECK: bb0([[RESULT:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_noparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_noparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[RESULT]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_noparam_oneresult'
sil @thunk_lowering_generic_noparam_oneresult : $@convention(thin) <T> () -> @out T {
bb0(%result : $*T):
%0 = function_ref @generic_noparam_oneresult_callee : $@convention(thin) <τ_0_0> () -> @out τ_0_0
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> () -> @out τ_0_0
%2 = apply %1(%result) : $@callee_guaranteed () -> @out T
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_oneparam_oneresult : $@convention(thin) <T> (@in T) -> @out T {
// CHECK: bb0([[RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_oneparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_oneparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: [[THUNKED_FUNC]]([[RESULT]], [[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_oneparam_oneresult'
sil @thunk_lowering_generic_oneparam_oneresult : $@convention(thin) <T> (@in T) -> @out T {
bb0(%result : $*T, %arg : $*T):
%0 = function_ref @generic_oneparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @out τ_0_0
%2 = apply %1(%result, %arg) : $@callee_guaranteed (@in T) -> @out T
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> @out T {
// CHECK: bb0([[RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_twoparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]([[RESULT]], [[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_twoparam_oneresult'
sil @thunk_lowering_generic_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> @out T {
bb0(%result : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_twoparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0
apply %1(%result, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> @out T
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_twoparam_oneresult_substituted_params : $@convention(thin) <T> (@in T, @in T) -> @out T {
// CHECK: bb0([[RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_twoparam_oneresult_substituted_params_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: [[CONVERT_TO_SUB_FORM_FUNC:%.*]] = convert_function [[THUNKED_FUNC]] :
// CHECK: apply [[CONVERT_TO_SUB_FORM_FUNC]]([[RESULT]], [[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_twoparam_oneresult_substituted_params'
sil @thunk_lowering_generic_twoparam_oneresult_substituted_params : $@convention(thin) <T> (@in T, @in T) -> @out T {
bb0(%result : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_twoparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0
%2 = convert_function %1 : $@callee_guaranteed (@in T, @in T) -> @out T to $@callee_guaranteed @substituted <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0 for <T>
apply %2(%result, %arg, %arg2) : $@callee_guaranteed @substituted <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @out τ_0_0 for <T>
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil @thunk_lowering_generic_mixed_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_mixed_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_mixed_twoparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: [[DIRECT_RESULT:%.*]] = apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]], [[ARG]], [[ARG2]]) :
// CHECK: return [[DIRECT_RESULT]] :
// CHECK: } // end sil function 'thunk_lowering_generic_mixed_twoparam_oneresult'
sil @thunk_lowering_generic_mixed_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass) {
bb0(%result : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_mixed_twoparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass)
%2 = apply %1(%result, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> (@out T, @owned Klass)
return %2 : $Klass
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_mixed_2_twoparam_oneresult_identity_0 : $@convention(thin) <T> (@in T, @in T, @guaranteed @convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass)) -> (@owned Klass, @out T, @owned Klass) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : $*T, [[THUNKED_FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass)):
// CHECK: [[DIRECT_RESULT:%.*]] = apply [[THUNKED_FUNC]]<T>([[INDIRECT_RESULT]], [[ARG1]], [[ARG2]]) :
// CHECK: return [[DIRECT_RESULT]]
// CHECK: } // end sil function 'thunk_lowering_generic_mixed_2_twoparam_oneresult_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_mixed_2_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_mixed_2_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_mixed_2_twoparam_oneresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: [[DIRECT_RESULT:%.*]] = apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]], [[ARG]], [[ARG2]]) :
// CHECK: return [[DIRECT_RESULT]]
// CHECK: } // end sil function 'thunk_lowering_generic_mixed_2_twoparam_oneresult'
sil @thunk_lowering_generic_mixed_2_twoparam_oneresult : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass) {
bb0(%result : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_mixed_2_twoparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass)
%2 = apply %1(%result, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> (@owned Klass, @out T, @owned Klass)
return %2 : $(Klass, Klass)
}
////////////////////////////////////
// MARK: Loadable Try Apply Tests //
////////////////////////////////////
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_noparam_noreturn_callee_identity_0 : $@convention(thin) (@guaranteed @convention(thin) () -> @error any Error) -> @error any Error {
// CHECK: bb0([[FUNC:%.*]] : $@convention(thin) () -> @error any Error):
// CHECK: try_apply [[FUNC]]() : $@convention(thin) () -> @error any Error, normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_noparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_noparam_noreturn_callee : $@convention(thin) () -> @error any Error {
// CHECK: [[FUNC:%.*]] = function_ref @throws_noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_noparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_throws_noparam_noreturn_callee'
sil @thunk_lowering_throws_noparam_noreturn_callee : $@convention(thin) () -> @error Error {
bb0:
%0 = function_ref @throws_noparam_noreturn_callee : $@convention(thin) () -> @error Error
%1 = thunk [identity] %0() : $@convention(thin) () -> @error Error
try_apply %1() : $@callee_guaranteed () -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_oneparam_noreturn_callee_identity_0 : $@convention(thin) (@owned Klass, @guaranteed @convention(thin) (@owned Klass) -> @error any Error) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[FUNC:%.*]] : $@convention(thin) (@owned Klass) -> @error any Error):
// CHECK: try_apply [[FUNC]]([[ARG]]) : $@convention(thin) (@owned Klass) -> @error any Error, normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_oneparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[FUNC:%.*]] = function_ref @throws_oneparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_oneparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_throws_oneparam_noreturn_callee'
sil @thunk_lowering_throws_oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> @error Error {
bb0(%arg : $Klass):
%0 = function_ref @throws_oneparam_noreturn_callee : $@convention(thin) (@owned Klass) -> @error Error
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass) -> @error Error
try_apply %1(%arg) : $@callee_guaranteed (@owned Klass) -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_twoparam_noreturn_callee_identity_0 : $@convention(thin) (@owned Klass, @owned Klass, @guaranteed @convention(thin) (@owned Klass, @owned Klass) -> @error any Error) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass, [[FUNC:%.*]] : $@convention(thin) (@owned Klass, @owned Klass) -> @error any Error):
// CHECK: try_apply [[FUNC]]([[ARG]], [[ARG2]]) :
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_twoparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @throws_twoparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_twoparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_throws_twoparam_noreturn_callee'
sil @thunk_lowering_throws_twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @error Error {
bb0(%arg : $Klass, %arg2 : $Klass):
%0 = function_ref @throws_twoparam_noreturn_callee : $@convention(thin) (@owned Klass, @owned Klass) -> @error Error
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass, @owned Klass) -> @error Error
try_apply %1(%arg, %arg2) : $@callee_guaranteed (@owned Klass, @owned Klass) -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_noparam_oneresult_callee_identity_0 : $@convention(thin) (@guaranteed @convention(thin) () -> (@owned Klass, @error any Error)) -> (@owned Klass, @error any Error) {
// CHECK: bb0([[FUNC:%.*]] : $@convention(thin) () -> (@owned Klass, @error any Error)):
// CHECK: try_apply [[FUNC]]() : $@convention(thin) () -> (@owned Klass, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[DIRECT_RESULT:%.*]] : $Klass)
// CHECK: return [[DIRECT_RESULT]] : $Klass
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_noparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_noparam_oneresult_callee : $@convention(thin) () -> (@owned Klass, @error any Error) {
// CHECK: [[FUNC:%.*]] = function_ref @throws_noparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_noparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_throws_noparam_oneresult_callee'
sil @thunk_lowering_throws_noparam_oneresult_callee : $@convention(thin) () -> (@owned Klass, @error Error) {
bb0:
%0 = function_ref @throws_noparam_oneresult_callee : $@convention(thin) () -> (@owned Klass, @error Error)
%1 = thunk [identity] %0() : $@convention(thin) () -> (@owned Klass, @error Error)
try_apply %1() : $@callee_guaranteed () -> (@owned Klass, @error Error), normal bb1, error bb2
bb1(%value : $Klass):
return %value : $Klass
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_oneparam_oneresult_callee_identity_0 : $@convention(thin) (@owned Klass, @guaranteed @convention(thin) (@owned Klass) -> (@owned Klass, @error any Error)) -> (@owned Klass, @error any Error) {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[FUNC:%.*]] : $@convention(thin) (@owned Klass) -> (@owned Klass, @error any Error)):
// CHECK: try_apply [[FUNC]]([[ARG]]) : $@convention(thin) (@owned Klass) -> (@owned Klass, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[DIRECT_RESULT:%.*]] : $Klass)
// CHECK: return [[DIRECT_RESULT]] : $Klass
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_oneparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> (@owned Klass, @error any Error) {
// CHECK: bb0([[ARG:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @throws_oneparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_oneparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_throws_oneparam_oneresult_callee'
sil @thunk_lowering_throws_oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> (@owned Klass, @error Error) {
bb0(%arg : $Klass):
%0 = function_ref @throws_oneparam_oneresult_callee : $@convention(thin) (@owned Klass) -> (@owned Klass, @error Error)
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass) -> (@owned Klass, @error Error)
try_apply %1(%arg) : $@callee_guaranteed (@owned Klass) -> (@owned Klass, @error Error), normal bb1, error bb2
bb1(%value : $Klass):
return %value : $Klass
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_throws_twoparam_oneresult_callee_identity_0 : $@convention(thin) (@owned Klass, @owned Klass, @guaranteed @convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error any Error)) -> (@owned Klass, @error any Error) {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass, [[FUNC:%.*]] : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error any Error)):
// CHECK: try_apply [[FUNC]]([[ARG]], [[ARG2]]) : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[DIRECT_RESULT:%.*]] : $Klass)
// CHECK: return [[DIRECT_RESULT]] : $Klass
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_throws_twoparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_throws_twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error any Error) {
// CHECK: bb0([[ARG:%.*]] : $Klass, [[ARG2:%.*]] : $Klass):
// CHECK: [[FUNC:%.*]] = function_ref @throws_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_throws_twoparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_throws_twoparam_oneresult_callee'
sil @thunk_lowering_throws_twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error Error) {
bb0(%arg : $Klass, %arg2 : $Klass):
%0 = function_ref @throws_twoparam_oneresult_callee : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error Error)
%1 = thunk [identity] %0() : $@convention(thin) (@owned Klass, @owned Klass) -> (@owned Klass, @error Error)
try_apply %1(%arg, %arg2) : $@callee_guaranteed (@owned Klass, @owned Klass) -> (@owned Klass, @error Error), normal bb1, error bb2
bb1(%value : $Klass):
return %value : $Klass
bb2(%error: $Error):
throw %error : $Error
}
///////////////////////////////////
// MARK: Generic Try Apply Tests //
///////////////////////////////////
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_noparam_noreturn_callee_identity_0 : $@convention(thin) <T> (@guaranteed @convention(thin) <T> () -> @error any Error) -> @error any Error {
// CHECK: bb0([[FUNC:%.*]] : $@convention(thin) <τ_0_0> () -> @error any Error):
// CHECK: try_apply [[FUNC]]<T>() : $@convention(thin) <τ_0_0> () -> @error any Error, normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_noparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_noparam_noreturn_callee : $@convention(thin) <T> () -> @error any Error {
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_noparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_noparam_noreturn_callee'
sil @thunk_lowering_generic_throws_noparam_noreturn_callee : $@convention(thin) <T> () -> @error Error {
bb0:
%0 = function_ref @generic_throws_noparam_noreturn_callee : $@convention(thin) <τ_0_0> () -> @error Error
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> () -> @error Error
try_apply %1() : $@callee_guaranteed () -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_oneparam_noreturn_callee_identity_0 : $@convention(thin) <T> (@in T, @guaranteed @convention(thin) <T> (@in T) -> @error any Error) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @error any Error):
// CHECK: try_apply [[FUNC]]<T>([[ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @error any Error, normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_oneparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_oneparam_noreturn_callee : $@convention(thin) <T> (@in T) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_oneparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_oneparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_oneparam_noreturn_callee'
sil @thunk_lowering_generic_throws_oneparam_noreturn_callee : $@convention(thin) <T> (@in T) -> @error Error {
bb0(%arg : $*T):
%0 = function_ref @generic_throws_oneparam_noreturn_callee : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @error Error
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @error Error
try_apply %1(%arg) : $@callee_guaranteed (@in T) -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_twoparam_noreturn_callee_identity_0 : $@convention(thin) <T> (@in T, @in T, @guaranteed @convention(thin) <T> (@in T, @in T) -> @error any Error) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> @error any Error):
// CHECK: try_apply [[FUNC]]<T>([[ARG]], [[ARG2]]) :
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_noreturn_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_twoparam_noreturn_callee : $@convention(thin) <T> (@in T, @in T) -> @error any Error {
// CHECK: bb0([[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_twoparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_twoparam_noreturn_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_noreturn_callee'
sil @thunk_lowering_generic_throws_twoparam_noreturn_callee : $@convention(thin) <T> (@in T, @in T) -> @error Error {
bb0(%arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_throws_twoparam_noreturn_callee : $@convention(thin) <T> (@in T, @in T) -> @error Error
%1 = thunk [identity] %0<T>() : $@convention(thin) <T> (@in T, @in T) -> @error Error
try_apply %1(%arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> @error Error, normal bb1, error bb2
bb1(%value : $()):
%9999 = tuple ()
return %9999 : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_noparam_oneresult_callee_identity_0 : $@convention(thin) <T> (@guaranteed @convention(thin) <T> () -> (@out T, @error any Error)) -> (@out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @error any Error)):
// CHECK: try_apply [[FUNC]]<T>([[INDIRECT_RESULT]]) : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[RESULT:%.*]] : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_noparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_noparam_oneresult_callee : $@convention(thin) <T> () -> (@out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] :
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_noparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_noparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_noparam_oneresult_callee'
sil @thunk_lowering_generic_throws_noparam_oneresult_callee : $@convention(thin) <T> () -> (@out T, @error Error) {
bb0(%result : $*T):
%0 = function_ref @generic_throws_noparam_oneresult_callee : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @error Error)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> () -> (@out τ_0_0, @error Error)
try_apply %1(%result) : $@callee_guaranteed () -> (@out T, @error Error), normal bb1, error bb2
bb1(%value : $()):
return %value : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_oneparam_oneresult_callee_identity_0 : $@convention(thin) <T> (@in T, @guaranteed @convention(thin) <T> (@in T) -> (@out T, @error any Error)) -> (@out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error)):
// CHECK: try_apply [[FUNC]]<T>([[INDIRECT_RESULT]], [[ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error any Error), normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_oneparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_oneparam_oneresult_callee : $@convention(thin) <T> (@in T) -> (@out T, @error any Error) {
// CHECK: bb0([[RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_oneparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_oneparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[RESULT]], [[ARG]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_oneparam_oneresult_callee'
sil @thunk_lowering_generic_throws_oneparam_oneresult_callee : $@convention(thin) <T> (@in T) -> (@out T, @error Error) {
bb0(%result : $*T, %arg : $*T):
%0 = function_ref @generic_throws_oneparam_oneresult_callee : $@convention(thin) <T> (@in T) -> (@out T, @error Error)
%1 = thunk [identity] %0<T>() : $@convention(thin) <T> (@in T) -> (@out T, @error Error)
try_apply %1(%result, %arg) : $@callee_guaranteed (@in T) -> (@out T, @error Error), normal bb1, error bb2
bb1(%value : $()):
return %value : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_twoparam_oneresult_callee_identity_0 : $@convention(thin) <T> (@in T, @in T, @guaranteed @convention(thin) <T> (@in T, @in T) -> (@out T, @error any Error)) -> (@out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @error any Error)):
// CHECK: try_apply [[FUNC]]<T>([[INDIRECT_RESULT]], [[ARG]], [[ARG2]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @error any Error), normal bb1, error bb2
//
// CHECK: bb1({{%.*}} : $()):
// CHECK: return
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_oneresult_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_twoparam_oneresult_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_twoparam_oneresult_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]], [[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_oneresult_callee'
sil @thunk_lowering_generic_throws_twoparam_oneresult_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @error Error) {
bb0(%result : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_throws_twoparam_oneresult_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @error Error)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @error Error)
try_apply %1(%result, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> (@out T, @error Error), normal bb1, error bb2
bb1(%value : $()):
return %value : $()
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_twoparam_mixedresults_callee_identity_0 : $@convention(thin) <T> (@in T, @in T, @guaranteed @convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass, @out T, @error any Error)) -> (@out T, @owned Klass, @out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[INDIRECT_RESULT_2:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass, @out τ_0_0, @error any Error)):
// CHECK: try_apply [[FUNC]]<T>([[INDIRECT_RESULT]], [[INDIRECT_RESULT_2]], [[ARG]], [[ARG2]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass, @out τ_0_0, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[RESULT:%.*]] : $Klass):
// CHECK: return [[RESULT]]
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_mixedresults_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_twoparam_mixedresults_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass, @out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[INDIRECT_RESULT_2:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_twoparam_mixedresults_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_twoparam_mixedresults_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]], [[INDIRECT_RESULT_2]], [[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_mixedresults_callee'
sil @thunk_lowering_generic_throws_twoparam_mixedresults_callee : $@convention(thin) <T> (@in T, @in T) -> (@out T, @owned Klass, @out T, @error Error) {
bb0(%result : $*T, %result2 : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_throws_twoparam_mixedresults_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass, @out τ_0_0, @error Error)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@out τ_0_0, @owned Klass, @out τ_0_0, @error Error)
try_apply %1(%result, %result2, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> (@out T, @owned Klass, @out T, @error Error), normal bb1, error bb2
bb1(%value : $Klass):
return %value : $Klass
bb2(%error: $Error):
throw %error : $Error
}
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_generic_throws_twoparam_mixedresults_2_callee_identity_0 : $@convention(thin) <T> (@in T, @in T, @guaranteed @convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass, @out T, @error any Error)) -> (@owned Klass, @out T, @owned Klass, @out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[INDIRECT_RESULT_2:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T, [[FUNC:%.*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass, @out τ_0_0, @error any Error)):
// CHECK: try_apply [[FUNC]]<T>([[INDIRECT_RESULT]], [[INDIRECT_RESULT_2]], [[ARG]], [[ARG2]]) : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass, @out τ_0_0, @error any Error), normal bb1, error bb2
//
// CHECK: bb1([[RESULT:%.*]] : $(Klass, Klass)):
// CHECK: return [[RESULT]]
//
// CHECK: bb2([[ERROR:%.*]] : $any Error):
// CHECK: throw [[ERROR]] :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_mixedresults_2_callee_identity_0'
// CHECK-LABEL: sil @thunk_lowering_generic_throws_twoparam_mixedresults_2_callee : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass, @out T, @error any Error) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[INDIRECT_RESULT_2:%.*]] : $*T, [[ARG:%.*]] : $*T, [[ARG2:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_throws_twoparam_mixedresults_2_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_generic_throws_twoparam_mixedresults_2_callee_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: try_apply [[THUNKED_FUNC]]([[INDIRECT_RESULT]], [[INDIRECT_RESULT_2]], [[ARG]], [[ARG2]]) :
// CHECK: } // end sil function 'thunk_lowering_generic_throws_twoparam_mixedresults_2_callee'
sil @thunk_lowering_generic_throws_twoparam_mixedresults_2_callee : $@convention(thin) <T> (@in T, @in T) -> (@owned Klass, @out T, @owned Klass, @out T, @error Error) {
bb0(%result : $*T, %result2 : $*T, %arg : $*T, %arg2 : $*T):
%0 = function_ref @generic_throws_twoparam_mixedresults_2_callee : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass, @out τ_0_0, @error Error)
%1 = thunk [identity] %0<T>() : $@convention(thin) <τ_0_0> (@in τ_0_0, @in τ_0_0) -> (@owned Klass, @out τ_0_0, @owned Klass, @out τ_0_0, @error Error)
try_apply %1(%result, %result2, %arg, %arg2) : $@callee_guaranteed (@in T, @in T) -> (@owned Klass, @out T, @owned Klass, @out T, @error Error), normal bb1, error bb2
bb1(%value : $(Klass, Klass)):
return %value : $(Klass, Klass)
bb2(%error: $Error):
throw %error : $Error
}
///////////////////////
// MARK: Async Tests //
///////////////////////
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_async_noparam_noresult_identity_0 : $@convention(thin) @async (@guaranteed @convention(thin) @async () -> ()) -> () {
// CHECK:bb0([[ARG:%.*]] : $@convention(thin) @async () -> ()):
// CHECK: apply [[ARG]]() : $@convention(thin) @async () -> ()
// CHECK: } // end sil function 'thunk_lowering_async_noparam_noresult_identity_0'
// CHECK-LABEL: sil @thunk_lowering_async_noparam_noresult : $@convention(thin) @async () -> () {
// CHECK: [[FUNC:%.*]] = function_ref @async_noparam_noreturn_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_async_noparam_noresult_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: apply [[THUNKED_FUNC]]() :
// CHECK: } // end sil function 'thunk_lowering_async_noparam_noresult'
sil @thunk_lowering_async_noparam_noresult : $@convention(thin) @async () -> () {
%0 = function_ref @async_noparam_noreturn_callee : $@convention(thin) @async () -> ()
%1 = thunk [identity] %0() : $@convention(thin) @async () -> ()
apply %1() : $@callee_guaranteed @async () -> ()
%9999 = tuple ()
return %9999 : $()
}
///////////////////////
// MARK: Yield Tests //
///////////////////////
// CHECK-LABEL: sil shared [thunk] @thunk_lowering_yield_test_identity_0 : $@yield_once @convention(thin) (@guaranteed @yield_once @convention(thin) () -> (@yields Klass, @yields Klass)) -> (@yields Klass, @yields Klass) {
// CHECK: bb0([[FUNC:%.*]] : $@yield_once @convention(thin) () -> (@yields Klass, @yields Klass)):
// CHECK: ([[RESULT1:%.*]], [[RESULT2:%.*]], [[TOKEN:%.*]]) = begin_apply [[FUNC]]() : $@yield_once @convention(thin) () -> (@yields Klass, @yields Klass)
// CHECK: yield ([[RESULT1]] : $Klass, [[RESULT2]] : $Klass), resume bb1, unwind bb2
//
// CHECK: bb1:
// CHECK: [[RESULT:%.*]] = end_apply [[TOKEN]] as $()
// CHECK: return [[RESULT]] : $()
//
// CHECK: bb2:
// CHECK: abort_apply [[TOKEN]]
// CHECK: unwind
// CHECK: } // end sil function 'thunk_lowering_yield_test_identity_0'
// CHECK-LABEL: sil @thunk_lowering_yield_test : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: [[FUNC:%.*]] = function_ref @yield_noparam_twoyield_callee :
// CHECK: [[THUNK:%.*]] = function_ref @thunk_lowering_yield_test_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[FUNC]]) :
// CHECK: ({{%.*}}, {{%.*}}, [[TOKEN:%.*]]) = begin_apply [[THUNKED_FUNC:%.*]]() :
// CHECK: end_apply [[TOKEN]]
// CHECK: } // end sil function 'thunk_lowering_yield_test'
sil @thunk_lowering_yield_test : $@convention(thin) () -> () {
bb0:
%0 = function_ref @yield_noparam_twoyield_callee : $@yield_once @convention(thin) () -> (@yields Klass, @yields Klass)
%1 = thunk [identity] %0() : $@yield_once @convention(thin) () -> (@yields Klass, @yields Klass)
(%result1, %result2, %tag) = begin_apply %1() : $@yield_once @callee_guaranteed () -> (@yields Klass, @yields Klass)
debug_value %result1 : $Klass
debug_value %result2 : $Klass
end_apply %tag as $()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil shared [thunk] @generic_thunk_lowering_yield_test_2_identity_0 : $@yield_once @convention(thin) <T> (@guaranteed @yield_once @convention(thin) <T> () -> (@yields Klass, @yields T, @yields Klass, @yields T)) -> (@yields Klass, @yields T, @yields Klass, @yields T) {
// CHECK: bb0([[FUNC:%.*]] : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0)):
// CHECK: ([[RESULT1:%.*]], [[RESULT2:%.*]], [[RESULT3:%.*]], [[RESULT4:%.*]], [[TOKEN:%.*]]) = begin_apply [[FUNC]]<T>() : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0)
// CHECK: yield ([[RESULT1]] : $Klass, [[RESULT2]] : $T, [[RESULT3]] : $Klass, [[RESULT4]] : $T), resume bb1, unwind bb2
//
// CHECK: bb1:
// CHECK: end_apply [[TOKEN]] as $()
// CHECK: return
//
// CHECK: bb2:
// CHECK: abort_apply [[TOKEN]]
// CHECK: unwind
// CHECK: } // end sil function 'generic_thunk_lowering_yield_test_2_identity_0'
// CHECK-LABEL: sil @generic_thunk_lowering_yield_test_2 : $@convention(thin) <T> () -> () {
// CHECK: bb0:
// CHECK: [[FUNC:%.*]] = function_ref @generic_yield_noparam_twoyield_callee :
// CHECK: [[THUNK:%.*]] = function_ref @generic_thunk_lowering_yield_test_2_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: ({{%.*}}, {{%.*}}, {{%.*}}, {{%.*}}, [[TOKEN:%.*]]) = begin_apply [[THUNKED_FUNC:%.*]]() :
// CHECK: end_apply [[TOKEN]]
// CHECK: } // end sil function 'generic_thunk_lowering_yield_test_2'
sil @generic_thunk_lowering_yield_test_2 : $@convention(thin) <T> () -> () {
bb0:
%0 = function_ref @generic_yield_noparam_twoyield_callee : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0)
%1 = thunk [identity] %0<T>() : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0)
(%result1, %result2, %result3, %result4, %tag) = begin_apply %1() : $@yield_once @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : Copyable, τ_0_0 : Escapable> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0) for <T>
debug_value %result1 : $Klass
debug_value %result2 : $T
debug_value %result3 : $Klass
debug_value %result4 : $T
end_apply %tag as $()
%9999 = tuple ()
return %9999 : $()
}
// CHECK-LABEL: sil shared [thunk] @generic_thunk_lowering_yield_test_mixed_identity_0 : $@yield_once @convention(thin) <T> (@guaranteed @yield_once @convention(thin) <T> () -> (@yields Klass, @yields T, @yields Klass, @yields T, @owned Klass, @out T, @owned Klass)) -> (@yields Klass, @yields T, @yields Klass, @yields T, @owned Klass, @out T, @owned Klass) {
// CHECK: bb0([[INDIRECT_RESULT:%.*]] : $*T, [[FUNC:%.*]] : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0, @owned Klass, @out τ_0_0, @owned Klass)):
// CHECK: ([[RESULT1:%.*]], [[RESULT2:%.*]], [[RESULT3:%.*]], [[RESULT4:%.*]], [[TOKEN:%.*]]) = begin_apply [[FUNC]]<T>([[INDIRECT_RESULT]]) : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0, @owned Klass, @out τ_0_0, @owned Klass)
// CHECK: yield ([[RESULT1]] : $Klass, [[RESULT2]] : $T, [[RESULT3]] : $Klass, [[RESULT4]] : $T), resume bb1, unwind bb2
//
// CHECK: bb1:
// CHECK: [[DIRECT_RESULT:%.*]] = end_apply [[TOKEN]] as $(Klass, Klass)
// CHECK: return [[DIRECT_RESULT]]
//
// CHECK: bb2:
// CHECK: abort_apply [[TOKEN]]
// CHECK: unwind
// CHECK: } // end sil function 'generic_thunk_lowering_yield_test_mixed_identity_0'
// CHECK-LABEL: sil @generic_thunk_lowering_yield_test_mixed : $@convention(thin) <T> () -> (@out T, @owned Klass, @owned Klass) {
// CHECK: bb0([[RESULT:%.*]] : $*T):
// CHECK: [[FUNC:%.*]] = function_ref @generic_yield_noparam_mixedyieldreturn_callee : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0, @owned Klass, @out τ_0_0, @owned Klass)
// CHECK: [[THUNK:%.*]] = function_ref @generic_thunk_lowering_yield_test_mixed_identity_0 :
// CHECK: [[THUNKED_FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[FUNC]]) :
// CHECK: ({{%.*}}, {{%.*}}, {{%.*}}, {{%.*}}, [[TOKEN:%.*]]) = begin_apply [[THUNKED_FUNC:%.*]]([[INDIRECT_RESULT]]) :
// CHECK: [[DIRECT_RESULT:%.*]] = end_apply [[TOKEN]]
// CHECK: return [[DIRECT_RESULT]]
// CHECK: } // end sil function 'generic_thunk_lowering_yield_test_mixed'
sil @generic_thunk_lowering_yield_test_mixed : $@convention(thin) <T> () -> (@out T, @owned Klass, @owned Klass) {
bb0(%result : $*T):
%0 = function_ref @generic_yield_noparam_mixedyieldreturn_callee : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @owned Klass, @yields τ_0_0, @yields Klass, @out τ_0_0, @yields τ_0_0, @owned Klass)
%1 = thunk [identity] %0<T>() : $@yield_once @convention(thin) <τ_0_0> () -> (@yields Klass, @owned Klass, @yields τ_0_0, @yields Klass, @out τ_0_0, @yields τ_0_0, @owned Klass)
(%yield1, %yield2, %yield3, %yield4, %tag) = begin_apply %1(%result) : $@yield_once @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : Copyable, τ_0_0 : Escapable> () -> (@yields Klass, @yields τ_0_0, @yields Klass, @yields τ_0_0, @owned Klass, @out τ_0_0, @owned Klass) for <T>
debug_value %yield1 : $Klass
debug_value %yield2 : $T
debug_value %yield3 : $Klass
debug_value %yield4 : $T
%directResult = end_apply %tag as $(Klass, Klass)
return %directResult : $(Klass, Klass)
}