Skip to content

Commit 2c6d597

Browse files
authored
Merge pull request swiftlang#21932 from rjmccall/thunk-anticanonicalizarianism
Fold "canonical" thunks into reabstraction thunks
2 parents 9b2a1cf + ecac762 commit 2c6d597

File tree

8 files changed

+100
-181
lines changed

8 files changed

+100
-181
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,6 +3208,8 @@ BEGIN_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)
32083208
return cast<GenericFunctionType>(fnType->getCanonicalType());
32093209
}
32103210

3211+
CanFunctionType substGenericArgs(SubstitutionMap subs) const;
3212+
32113213
CanGenericSignature getGenericSignature() const {
32123214
return CanGenericSignature(getPointer()->getGenericSignature());
32133215
}

lib/AST/Type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2683,6 +2683,12 @@ GenericFunctionType::substGenericArgs(SubstitutionMap subs) {
26832683
substFn->getResult(), getExtInfo());
26842684
}
26852685

2686+
CanFunctionType
2687+
CanGenericFunctionType::substGenericArgs(SubstitutionMap subs) const {
2688+
return cast<FunctionType>(
2689+
getPointer()->substGenericArgs(subs)->getCanonicalType());
2690+
}
2691+
26862692
static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
26872693
Type origBase,
26882694
Type substBase,

lib/SIL/SILFunctionType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2663,8 +2663,10 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
26632663
AnyFunctionType::Param selfParam = fnType.getParams()[0];
26642664

26652665
// The formal method parameters.
2666+
// If we actually partially-apply this, assume we'll need a thick function.
26662667
fnType = cast<FunctionType>(fnType.getResult());
2667-
auto innerExtInfo = fnType->getExtInfo();
2668+
auto innerExtInfo =
2669+
fnType->getExtInfo().withRepresentation(FunctionTypeRepresentation::Swift);
26682670
auto methodParams = fnType->getParams();
26692671

26702672
auto resultType = fnType.getResult();

lib/SILGen/SILGenFunction.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -668,12 +668,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
668668
CanAnyFunctionType blockTy,
669669
CanSILFunctionType loweredBlockTy);
670670

671-
/// Given a non-canonical function type, create a thunk for the function's
672-
/// canonical type.
673-
ManagedValue emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
674-
CanSILFunctionType nonCanonicalTy,
675-
CanSILFunctionType canonicalTy);
676-
677671
/// Thunk with the signature of a base class method calling a derived class
678672
/// method.
679673
///

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ static void forwardFunctionArguments(SILGenFunction &SGF,
15951595
auto &arg = managedArgs[index];
15961596
auto argTy = argTypes[index];
15971597
if (argTy.isConsumed()) {
1598-
forwardedArgs.push_back(arg.forward(SGF));
1598+
forwardedArgs.push_back(arg.ensurePlusOne(SGF, loc).forward(SGF));
15991599
continue;
16001600
}
16011601

@@ -3906,150 +3906,3 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy,
39063906
scope.pop();
39073907
B.createReturn(loc, reqtResultValue);
39083908
}
3909-
3910-
//===----------------------------------------------------------------------===//
3911-
// Conversion to Canonical SILFunctionType Thunks
3912-
//===----------------------------------------------------------------------===//
3913-
3914-
static void translateParametersForCanonicalFunctionThunk(
3915-
SILGenFunction &SGF, SILLocation loc,
3916-
ArrayRef<ManagedValue> origParamValues,
3917-
ArrayRef<SILParameterInfo> newParamInfos,
3918-
SmallVectorImpl<ManagedValue> &newParams) {
3919-
assert(origParamValues.size() == newParamInfos.size());
3920-
3921-
for (auto T : llvm::zip(origParamValues, newParamInfos)) {
3922-
ManagedValue origParam;
3923-
SILParameterInfo newParamInfo;
3924-
std::tie(origParam, newParamInfo) = T;
3925-
3926-
if (origParam.getType().isTrivial(SGF.getModule())) {
3927-
newParams.emplace_back(origParam);
3928-
continue;
3929-
}
3930-
3931-
if (origParam.hasCleanup()) {
3932-
// If we have a +1 value and the non-canonical function expects a
3933-
// guaranteed parameter, borrow the parameter. Otherwise just pass off the
3934-
// +1 value.
3935-
if (newParamInfo.isGuaranteed()) {
3936-
origParam = origParam.borrow(SGF, loc);
3937-
}
3938-
newParams.emplace_back(origParam);
3939-
continue;
3940-
}
3941-
3942-
// Otherwise, if we have a +0 value and we want to pass it off as a +1
3943-
// value, perform the copy.
3944-
if (newParamInfo.isConsumed()) {
3945-
origParam = origParam.copy(SGF, loc);
3946-
}
3947-
newParams.emplace_back(origParam);
3948-
}
3949-
}
3950-
3951-
static void buildCanonicalFunctionThunkBody(SILGenFunction &SGF,
3952-
SILLocation loc,
3953-
CanSILFunctionType nonCanonicalTy,
3954-
CanSILFunctionType canonicalTy) {
3955-
SGF.F.setBare(IsBare);
3956-
SGF.F.setThunk(IsThunk);
3957-
3958-
FullExpr scope(SGF.Cleanups, CleanupLocation::get(loc));
3959-
FormalEvaluationScope formalEvalScope(SGF);
3960-
3961-
// Collect the thunk params, creating arguments for each parameter.
3962-
SmallVector<ManagedValue, 8> origParams;
3963-
SGF.collectThunkParams(loc, origParams);
3964-
3965-
// Then translate our parameters into new params.
3966-
SmallVector<ManagedValue, 8> newParams;
3967-
translateParametersForCanonicalFunctionThunk(
3968-
SGF, loc,
3969-
// We drop the front so we don't process the thunked function here. We
3970-
// handle that later.
3971-
llvm::makeArrayRef(origParams).drop_back(1),
3972-
nonCanonicalTy->getParameters(), newParams);
3973-
3974-
// Then grab the function we are going to call from the last parameter.
3975-
ManagedValue fn = origParams.back();
3976-
3977-
// Collect the arguments.
3978-
SmallVector<SILValue, 8> args;
3979-
3980-
// Add all of the indirect results. We can just add the SILValues directly to
3981-
// the args array since we do not need to perform any transformations upon
3982-
// them because:
3983-
//
3984-
// 1. Reabstraction can not occur as a result of a canonical/non-canonical
3985-
// mismatch.
3986-
// 2. SILGenFunction::collectThunkParams(...) does not create cleanups when it
3987-
// creates arguments.
3988-
SILFunctionConventions fnConv(canonicalTy, SGF.SGM.M);
3989-
transform(range(fnConv.getNumIndirectSILResults()), std::back_inserter(args),
3990-
[&](unsigned Index) -> SILValue {
3991-
return SGF.F.begin()->getArgument(Index);
3992-
});
3993-
3994-
// and then the rest of the arguments besides the first argument. Here we have
3995-
// to forward the arguments since collectThunkParams /does/ create cleanups
3996-
// for the parameters.
3997-
forwardFunctionArguments(SGF, loc, nonCanonicalTy, newParams, args);
3998-
3999-
// Perform the call.
4000-
SILValue result =
4001-
SGF.emitApplyWithRethrow(loc, fn.forward(SGF), fn.getType(), {}, args);
4002-
4003-
formalEvalScope.pop();
4004-
scope.pop();
4005-
SGF.B.createReturn(loc, result);
4006-
}
4007-
4008-
ManagedValue
4009-
SILGenFunction::emitCanonicalFunctionThunk(SILLocation loc, ManagedValue fn,
4010-
CanSILFunctionType nonCanonicalTy,
4011-
CanSILFunctionType canonicalTy) {
4012-
canonicalTy = canonicalTy->getWithRepresentation(
4013-
SILFunctionType::Representation::Thick);
4014-
4015-
SubstitutionMap contextSubs, interfaceSubs;
4016-
GenericEnvironment *genericEnv = nullptr;
4017-
4018-
// These two are not used here -- but really, bridging thunks
4019-
// should be emitted using the formal AST type, not the lowered
4020-
// type
4021-
CanType inputSubstType;
4022-
CanType outputSubstType;
4023-
CanType dynamicSelfType;
4024-
auto thunkTy = buildThunkType(nonCanonicalTy, canonicalTy, inputSubstType,
4025-
outputSubstType, genericEnv, interfaceSubs,
4026-
dynamicSelfType);
4027-
assert(!dynamicSelfType && "not implemented");
4028-
auto thunk = SGM.getOrCreateReabstractionThunk(thunkTy, nonCanonicalTy,
4029-
canonicalTy, F.isSerialized());
4030-
if (thunk->empty()) {
4031-
thunk->setGenericEnvironment(genericEnv);
4032-
SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
4033-
auto loc = RegularLocation::getAutoGeneratedLocation();
4034-
buildCanonicalFunctionThunkBody(thunkSGF, loc, nonCanonicalTy, canonicalTy);
4035-
}
4036-
4037-
CanSILFunctionType substFnTy = thunkTy;
4038-
4039-
if (thunkTy->getGenericSignature()) {
4040-
substFnTy = thunkTy->substGenericArgs(F.getModule(), interfaceSubs);
4041-
}
4042-
4043-
// Create it in the current function.
4044-
auto thunkValue = B.createFunctionRefFor(loc, thunk);
4045-
ManagedValue thunkedFn = B.createPartialApply(
4046-
loc, thunkValue, SILType::getPrimitiveObjectType(substFnTy),
4047-
interfaceSubs, {fn},
4048-
SILType::getPrimitiveObjectType(canonicalTy));
4049-
if (canonicalTy->isNoEscape()) {
4050-
auto &funcTL = getTypeLowering(canonicalTy);
4051-
thunkedFn =
4052-
B.createConvertFunction(loc, thunkedFn, funcTL.getLoweredType());
4053-
}
4054-
return thunkedFn;
4055-
}

lib/SILGen/SILGenThunk.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,38 +86,41 @@ SILGenFunction::emitDynamicMethodRef(SILLocation loc, SILDeclRef constant,
8686
return ManagedValue::forUnmanaged(B.createFunctionRefFor(loc, F));
8787
}
8888

89-
static ManagedValue getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc,
90-
SILDeclRef thunk,
91-
ManagedValue selfArg,
92-
SubstitutionMap curriedSubs) {
89+
static std::pair<ManagedValue, SILDeclRef>
90+
getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk,
91+
ManagedValue selfArg, SubstitutionMap curriedSubs) {
9392
auto *vd = thunk.getDecl();
9493

9594
// Reference the next uncurrying level of the function.
9695
SILDeclRef next = SILDeclRef(vd, thunk.kind);
9796
assert(!next.isCurried);
9897

98+
auto constantInfo = SGF.SGM.Types.getConstantInfo(next);
99+
99100
// If the function is natively foreign, reference its foreign entry point.
100101
if (requiresForeignToNativeThunk(vd))
101-
return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
102+
return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
103+
next};
102104

103105
// If the thunk is a curry thunk for a direct method reference, we are
104106
// doing a direct dispatch (eg, a fragile 'super.foo()' call).
105107
if (thunk.isDirectReference)
106-
return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
107-
108-
auto constantInfo = SGF.SGM.Types.getConstantInfo(next);
108+
return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
109+
next};
109110

110111
if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
111112
if (getMethodDispatch(func) == MethodDispatch::Class) {
112113
// Use the dynamic thunk if dynamic.
113114
if (vd->isObjCDynamic()) {
114-
return SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType);
115+
return {SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType),
116+
next};
115117
}
116118

117119
auto methodTy = SGF.SGM.Types.getConstantOverrideType(next);
118120
SILValue result =
119121
SGF.emitClassMethodRef(loc, selfArg.getValue(), next, methodTy);
120-
return ManagedValue::forUnmanaged(result);
122+
return {ManagedValue::forUnmanaged(result),
123+
next.getOverriddenVTableEntry()};
121124
}
122125

123126
// If the fully-uncurried reference is to a generic method, look up the
@@ -130,12 +133,13 @@ static ManagedValue getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc,
130133
auto conformance = curriedSubs.lookupConformance(origSelfType, protocol);
131134
auto result = SGF.B.createWitnessMethod(loc, substSelfType, *conformance,
132135
next, constantInfo.getSILType());
133-
return ManagedValue::forUnmanaged(result);
136+
return {ManagedValue::forUnmanaged(result), next};
134137
}
135138
}
136139

137140
// Otherwise, emit a direct call.
138-
return ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next));
141+
return {ManagedValue::forUnmanaged(SGF.emitGlobalFunctionRef(loc, next)),
142+
next};
139143
}
140144

141145
void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
@@ -152,7 +156,8 @@ void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
152156
SILLocation loc(vd);
153157
Scope S(*this, vd);
154158

155-
auto thunkFnTy = SGM.Types.getConstantInfo(thunk).SILFnType;
159+
auto thunkInfo = SGM.Types.getConstantInfo(thunk);
160+
auto thunkFnTy = thunkInfo.SILFnType;
156161
SILFunctionConventions fromConv(thunkFnTy, SGM.M);
157162

158163
auto selfTy = fromConv.getSILType(thunkFnTy->getSelfParameter());
@@ -162,11 +167,10 @@ void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
162167
// Forward substitutions.
163168
auto subs = F.getForwardingSubstitutionMap();
164169

165-
ManagedValue toFn = getNextUncurryLevelRef(*this, loc, thunk, selfArg, subs);
170+
auto toFnAndRef = getNextUncurryLevelRef(*this, loc, thunk, selfArg, subs);
171+
ManagedValue toFn = toFnAndRef.first;
172+
SILDeclRef calleeRef = toFnAndRef.second;
166173

167-
// FIXME: Using the type from the ConstantInfo instead of looking at
168-
// getConstantOverrideInfo() for methods looks suspect in the presence
169-
// of covariant overrides and multiple vtable entries.
170174
SILType resultTy = fromConv.getSingleSILResultType();
171175
resultTy = F.mapTypeIntoContext(resultTy);
172176
auto substTy = toFn.getType().substGenericArgs(SGM.M, subs);
@@ -184,8 +188,27 @@ void SILGenFunction::emitCurryThunk(SILDeclRef thunk) {
184188
if (resultFnTy->isABICompatibleWith(closureFnTy).isCompatible()) {
185189
toClosure = B.createConvertFunction(loc, toClosure, resultTy);
186190
} else {
191+
// Compute the partially-applied abstraction pattern for the callee:
192+
// just grab the pattern for the curried fn ref and "call" it.
193+
assert(!calleeRef.isCurried);
194+
calleeRef.isCurried = true;
195+
auto appliedFnPattern = SGM.Types.getConstantInfo(calleeRef).FormalPattern
196+
.getFunctionResultType();
197+
198+
auto appliedThunkPattern =
199+
thunkInfo.FormalPattern.getFunctionResultType();
200+
201+
// The formal type should be the same for the callee and the thunk.
202+
auto formalType = thunkInfo.FormalType;
203+
if (auto genericSubstType = dyn_cast<GenericFunctionType>(formalType)) {
204+
formalType = genericSubstType.substGenericArgs(subs);
205+
}
206+
formalType = cast<AnyFunctionType>(formalType.getResult());
207+
187208
toClosure =
188-
emitCanonicalFunctionThunk(loc, toClosure, closureFnTy, resultFnTy);
209+
emitTransformedValue(loc, toClosure,
210+
appliedFnPattern, formalType,
211+
appliedThunkPattern, formalType);
189212
}
190213
}
191214
toClosure = S.popPreservingValue(toClosure);

test/SILGen/guaranteed_normal_args_curry_thunks.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ struct AddrOnlyStructInitGeneric<T> {
119119
// CHECK: return [[THUNK_PA]]
120120
// CHECK: } // end sil function '$ss017LoadableClassInitA0CyABs5KlassCcfCTcTd'
121121

122-
// Canonical Thunk.
122+
// Reabstraction thunk.
123123
//
124-
// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCs017LoadableClassInitB0CIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable) -> @owned LoadableClassInitLoadable {
124+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs017LoadableClassInitB0CIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable) -> @owned LoadableClassInitLoadable {
125125
// CHECK: bb0([[CLASS:%.*]] : @guaranteed $Klass, [[PA:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @owned LoadableClassInitLoadable):
126126
// CHECK: [[CLASS_COPY:%.*]] = copy_value [[CLASS]]
127127
// CHECK: [[RESULT:%.*]] = apply [[PA]]([[CLASS_COPY]])
@@ -153,9 +153,9 @@ func testLoadableClassInitLoadable() {
153153
// CHECK: return [[THUNK_PA]]
154154
// CHECK: } // end sil function '$ss018LoadableStructInitA0VyABs5KlassCcfCTc'
155155

156-
// Canonical Thunk.
156+
// Reabstraction thunk.
157157
//
158-
// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCs018LoadableStructInitB0VIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable) -> @owned LoadableStructInitLoadable {
158+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs018LoadableStructInitB0VIegxo_AbDIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable) -> @owned LoadableStructInitLoadable {
159159
// CHECK: bb0([[CLASS:%.*]] : @guaranteed $Klass, [[PA:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @owned LoadableStructInitLoadable):
160160
// CHECK: [[CLASS_COPY:%.*]] = copy_value [[CLASS]]
161161
// CHECK: [[RESULT:%.*]] = apply [[PA]]([[CLASS_COPY]])
@@ -191,14 +191,14 @@ func testLoadableStructInitLoadable() {
191191
// CHECK: return [[THUNK]]
192192
// CHECK: } // end sil function '$ss25AddrOnlyStructInitGenericVyAByxGxcfCTc'
193193

194-
// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR : $@convention(thin) <T> (@in_guaranteed T, @guaranteed @callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>) -> @out AddrOnlyStructInitGeneric<T> {
194+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR : $@convention(thin) <T> (@in_guaranteed T, @guaranteed @callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>) -> @out AddrOnlyStructInitGeneric<T> {
195195
// CHECK: bb0([[ARG0:%.*]] : $*AddrOnlyStructInitGeneric<T>, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>):
196196
// CHECK: [[STACK:%.*]] = alloc_stack $T
197197
// CHECK: copy_addr [[ARG1]] to [initialization] [[STACK]] : $*T
198198
// CHECK: apply [[ARG2]]([[ARG0]], [[STACK]]) : $@callee_guaranteed (@in T) -> @out AddrOnlyStructInitGeneric<T>
199199
// CHECK: } // end sil function '$sxs25AddrOnlyStructInitGenericVyxGIegir_xACIegnr_lTR'
200200

201-
// CHECK_LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs25AddrOnlyStructInitGenericVyABGIegnr_AbEIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>) -> @owned AddrOnlyStructInitGeneric<Klass> {
201+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCs25AddrOnlyStructInitGenericVyABGIegnr_AbEIeggo_TR : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>) -> @owned AddrOnlyStructInitGeneric<Klass> {
202202
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Klass, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed Klass) -> @out AddrOnlyStructInitGeneric<Klass>):
203203
// CHECK: [[STACK:%.*]] = alloc_stack $Klass
204204
// CHECK: [[ARG0_COPY:%.*]] = copy_value [[ARG0]]
@@ -253,9 +253,9 @@ func testAddrOnlyStructInitGenericAddrOnly<T : ProtocolInitAddressOnly>(t: T) {
253253
// CHECK: return [[CANONICAL_THUNK]]
254254
// CHECK: } // end sil function '$ss20ProtocolInitLoadableP1txs5KlassC_tcfCTc'
255255

256-
// Canonical thunk
256+
// Reabstraction thunk.
257257
//
258-
// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] [ossa] @$ss5KlassCxIegxr_ABxIeggr_s20ProtocolInitLoadableRzlTR : $@convention(thin) <Self where Self : ProtocolInitLoadable> (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @out Self) -> @out Self {
258+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$ss5KlassCxIegxr_ABxIeggr_s20ProtocolInitLoadableRzlTR : $@convention(thin) <Self where Self : ProtocolInitLoadable> (@guaranteed Klass, @guaranteed @callee_guaranteed (@owned Klass) -> @out Self) -> @out Self {
259259
// CHECK: bb0([[ARG0:%.*]] : $*Self, [[ARG1:%.*]] : @guaranteed $Klass, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@owned Klass) -> @out Self):
260260
// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
261261
// CHECK: apply [[ARG2]]([[ARG0]], [[ARG1_COPY]])

0 commit comments

Comments
 (0)