Skip to content

Commit f63be76

Browse files
authored
Merge pull request #80622 from gottesmm/pr-9c92d645ac34f929bbaf39f2f26aa2e3e3acf5cb
[concurrency] Implement protocol witness thunking in SILGen for @execution(caller)/@execution(concurrent).
2 parents 6ceb9c1 + 04b845c commit f63be76

File tree

4 files changed

+278
-68
lines changed

4 files changed

+278
-68
lines changed

lib/SILGen/SILGenFunction.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -2603,8 +2603,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
26032603

26042604
enum class ThunkGenFlag {
26052605
None,
2606-
ConvertingToNonIsolatedCaller,
2607-
ConvertingFromNonIsolatedCaller,
2606+
2607+
/// Set if the thunk has an implicit isolated parameter.
2608+
///
2609+
/// The implication is that we shouldn't forward that parameter into the
2610+
/// callee as a normal parameter (if the callee has an implicit param, we
2611+
/// handle it through a different code path).
2612+
ThunkHasImplicitIsolatedParam = 0x1,
2613+
2614+
/// Set if the callee has an implicit isolated parameter that we need to
2615+
/// find the appropriate value for when we call it from the thunk.
2616+
CalleeHasImplicitIsolatedParam = 0x2,
26082617
};
26092618
using ThunkGenOptions = OptionSet<ThunkGenFlag>;
26102619

lib/SILGen/SILGenPoly.cpp

+138-66
Original file line numberDiff line numberDiff line change
@@ -1025,10 +1025,9 @@ void SILGenFunction::collectThunkParams(
10251025
auto functionArgument =
10261026
B.createInputFunctionArgument(inContextParamTy, loc);
10271027

1028-
// If we are told to not propagate the isolated parameter and this is the
1029-
// implicit leading/isolated parameter, continue.
1030-
if (options.contains(ThunkGenFlag::ConvertingToNonIsolatedCaller) &&
1031-
param.hasOption(SILParameterInfo::ImplicitLeading) &&
1028+
// If our thunk has an implicit param and we are being asked to forward it,
1029+
// to the callee, skip it. We are going to handle it especially later.
1030+
if (param.hasOption(SILParameterInfo::ImplicitLeading) &&
10321031
param.hasOption(SILParameterInfo::Isolated))
10331032
continue;
10341033
params.push_back(functionArgument);
@@ -2925,8 +2924,11 @@ forwardFunctionArguments(SILGenFunction &SGF, SILLocation loc,
29252924
SmallVectorImpl<SILValue> &forwardedArgs,
29262925
SILGenFunction::ThunkGenOptions options = {}) {
29272926
auto argTypes = fTy->getParameters();
2927+
2928+
// If our callee has an implicit parameter, we have already inserted it, so
2929+
// drop it from argTypes.
29282930
if (options.contains(
2929-
SILGenFunction::ThunkGenFlag::ConvertingFromNonIsolatedCaller)) {
2931+
SILGenFunction::ThunkGenFlag::CalleeHasImplicitIsolatedParam)) {
29302932
argTypes = argTypes.drop_front();
29312933
}
29322934

@@ -5453,16 +5455,11 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
54535455
// isolated parameter preventing us from having to memcpy over the array.
54545456
if (outputSubstType->isAsync()) {
54555457
if (outputSubstType->getIsolation().getKind() ==
5456-
FunctionTypeIsolation::Kind::NonIsolatedCaller &&
5457-
inputSubstType->getIsolation().getKind() !=
5458-
FunctionTypeIsolation::Kind::NonIsolatedCaller)
5459-
options |= ThunkGenFlag::ConvertingToNonIsolatedCaller;
5460-
5461-
if (outputSubstType->getIsolation().getKind() !=
5462-
FunctionTypeIsolation::Kind::NonIsolatedCaller &&
5463-
inputSubstType->getIsolation().getKind() ==
5464-
FunctionTypeIsolation::Kind::NonIsolatedCaller)
5465-
options |= ThunkGenFlag::ConvertingFromNonIsolatedCaller;
5458+
FunctionTypeIsolation::Kind::NonIsolatedCaller)
5459+
options |= ThunkGenFlag::ThunkHasImplicitIsolatedParam;
5460+
if (inputSubstType->getIsolation().getKind() ==
5461+
FunctionTypeIsolation::Kind::NonIsolatedCaller)
5462+
options |= ThunkGenFlag::CalleeHasImplicitIsolatedParam;
54665463
}
54675464

54685465
SmallVector<ManagedValue, 8> params;
@@ -5485,14 +5482,16 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
54855482
outputErasedIsolation = params.pop_back_val();
54865483
}
54875484

5488-
if (!SGF.F.maybeGetIsolatedArgument() && argTypes.size() &&
5485+
if (argTypes.size() &&
54895486
argTypes.front().hasOption(SILParameterInfo::Isolated) &&
54905487
argTypes.front().hasOption(SILParameterInfo::ImplicitLeading))
5491-
options |= ThunkGenFlag::ConvertingFromNonIsolatedCaller;
5488+
options |= ThunkGenFlag::CalleeHasImplicitIsolatedParam;
54925489

5493-
// If we are converting to nonisolated caller, we are going to have an extra
5494-
// parameter in our argTypes that we need to drop.
5495-
if (options.contains(ThunkGenFlag::ConvertingFromNonIsolatedCaller))
5490+
// If we are converting from a nonisolated caller, we are going to have an
5491+
// extra parameter in our argTypes that we need to drop. We are going to
5492+
// handle it separately later so that TranslateArguments does not have to know
5493+
// anything about it.
5494+
if (options.contains(ThunkGenFlag::CalleeHasImplicitIsolatedParam))
54965495
argTypes = argTypes.drop_front();
54975496

54985497
// We may need to establish the right executor for the input function.
@@ -5597,7 +5596,7 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
55975596

55985597
// If we are thunking a nonisolated caller to nonisolated or global actor, we
55995598
// need to load the actor.
5600-
if (options.contains(ThunkGenFlag::ConvertingFromNonIsolatedCaller)) {
5599+
if (options.contains(ThunkGenFlag::CalleeHasImplicitIsolatedParam)) {
56015600
auto outputIsolation = outputSubstType->getIsolation();
56025601
switch (outputIsolation.getKind()) {
56035602
case FunctionTypeIsolation::Kind::NonIsolated:
@@ -7264,11 +7263,60 @@ void SILGenFunction::emitProtocolWitness(
72647263
FullExpr scope(Cleanups, cleanupLoc);
72657264
FormalEvaluationScope formalEvalScope(*this);
72667265

7266+
// Grab the type of our thunk.
72677267
auto thunkTy = F.getLoweredFunctionType();
72687268

7269+
// Then get the type of the witness.
7270+
auto witnessKind = getWitnessDispatchKind(witness, isSelfConformance);
7271+
auto witnessInfo = getConstantInfo(getTypeExpansionContext(), witness);
7272+
CanAnyFunctionType witnessSubstTy = witnessInfo.LoweredType;
7273+
if (auto genericFnType = dyn_cast<GenericFunctionType>(witnessSubstTy)) {
7274+
witnessSubstTy = cast<FunctionType>(
7275+
genericFnType->substGenericArgs(witnessSubs)->getCanonicalType());
7276+
}
7277+
7278+
assert(!witnessSubstTy->hasError());
7279+
7280+
if (auto genericFnType = dyn_cast<GenericFunctionType>(reqtSubstTy)) {
7281+
auto forwardingSubs = F.getForwardingSubstitutionMap();
7282+
reqtSubstTy = cast<FunctionType>(
7283+
genericFnType->substGenericArgs(forwardingSubs)->getCanonicalType());
7284+
} else {
7285+
reqtSubstTy = cast<FunctionType>(
7286+
F.mapTypeIntoContext(reqtSubstTy)->getCanonicalType());
7287+
}
7288+
7289+
assert(!reqtSubstTy->hasError());
7290+
7291+
// Get the lowered type of the witness.
7292+
auto origWitnessFTy = getWitnessFunctionType(getTypeExpansionContext(), SGM,
7293+
witness, witnessKind);
7294+
auto witnessFTy = origWitnessFTy;
7295+
if (!witnessSubs.empty()) {
7296+
witnessFTy = origWitnessFTy->substGenericArgs(SGM.M, witnessSubs,
7297+
getTypeExpansionContext());
7298+
}
7299+
7300+
// Now that we have the type information in hand, we can generate the thunk
7301+
// body.
7302+
7303+
using ThunkGenFlag = SILGenFunction::ThunkGenFlag;
7304+
auto options = SILGenFunction::ThunkGenOptions();
7305+
7306+
{
7307+
auto thunkIsolatedParam = thunkTy->maybeGetIsolatedParameter();
7308+
if (thunkIsolatedParam &&
7309+
thunkIsolatedParam->hasOption(SILParameterInfo::ImplicitLeading))
7310+
options |= ThunkGenFlag::ThunkHasImplicitIsolatedParam;
7311+
auto witnessIsolatedParam = witnessFTy->maybeGetIsolatedParameter();
7312+
if (witnessIsolatedParam &&
7313+
witnessIsolatedParam->hasOption(SILParameterInfo::ImplicitLeading))
7314+
options |= ThunkGenFlag::CalleeHasImplicitIsolatedParam;
7315+
}
7316+
72697317
SmallVector<ManagedValue, 8> origParams;
72707318
SmallVector<ManagedValue, 8> thunkIndirectResults;
7271-
collectThunkParams(loc, origParams, &thunkIndirectResults);
7319+
collectThunkParams(loc, origParams, &thunkIndirectResults, nullptr, options);
72727320

72737321
if (witness.getDecl()->requiresUnavailableDeclABICompatibilityStubs())
72747322
emitApplyOfUnavailableCodeReached();
@@ -7305,40 +7353,7 @@ void SILGenFunction::emitProtocolWitness(
73057353
}
73067354
}
73077355

7308-
// Get the type of the witness.
7309-
auto witnessKind = getWitnessDispatchKind(witness, isSelfConformance);
7310-
auto witnessInfo = getConstantInfo(getTypeExpansionContext(), witness);
7311-
CanAnyFunctionType witnessSubstTy = witnessInfo.LoweredType;
7312-
if (auto genericFnType = dyn_cast<GenericFunctionType>(witnessSubstTy)) {
7313-
witnessSubstTy = cast<FunctionType>(genericFnType
7314-
->substGenericArgs(witnessSubs)
7315-
->getCanonicalType());
7316-
}
7317-
7318-
assert(!witnessSubstTy->hasError());
7319-
7320-
if (auto genericFnType = dyn_cast<GenericFunctionType>(reqtSubstTy)) {
7321-
auto forwardingSubs = F.getForwardingSubstitutionMap();
7322-
reqtSubstTy = cast<FunctionType>(genericFnType
7323-
->substGenericArgs(forwardingSubs)
7324-
->getCanonicalType());
7325-
} else {
7326-
reqtSubstTy = cast<FunctionType>(F.mapTypeIntoContext(reqtSubstTy)
7327-
->getCanonicalType());
7328-
}
7329-
7330-
assert(!reqtSubstTy->hasError());
7331-
7332-
// Get the lowered type of the witness.
7333-
auto origWitnessFTy = getWitnessFunctionType(getTypeExpansionContext(), SGM,
7334-
witness, witnessKind);
7335-
auto witnessFTy = origWitnessFTy;
7336-
if (!witnessSubs.empty()) {
7337-
witnessFTy = origWitnessFTy->substGenericArgs(SGM.M, witnessSubs,
7338-
getTypeExpansionContext());
7339-
}
73407356
auto witnessUnsubstTy = witnessFTy->getUnsubstitutedType(SGM.M);
7341-
73427357
auto reqtSubstParams = reqtSubstTy.getParams();
73437358
auto witnessSubstParams = witnessSubstTy.getParams();
73447359

@@ -7360,8 +7375,8 @@ void SILGenFunction::emitProtocolWitness(
73607375
// @convention(c) () -> ()
73617376
// . We do this by simply omitting the last params.
73627377
// TODO: fix this for static C++ methods.
7363-
if (witness.getDecl()->getClangDecl() &&
7364-
isa<clang::CXXConstructorDecl>(witness.getDecl()->getClangDecl())) {
7378+
if (isa_and_nonnull<clang::CXXConstructorDecl>(
7379+
witness.getDecl()->getClangDecl())) {
73657380
origParams.pop_back();
73667381
reqtSubstParams = reqtSubstParams.drop_back();
73677382
ignoreFinalInputOrigParam = true;
@@ -7379,15 +7394,19 @@ void SILGenFunction::emitProtocolWitness(
73797394
// Translate the argument values from the requirement abstraction level to
73807395
// the substituted signature of the witness.
73817396
SmallVector<ManagedValue, 8> witnessParams;
7397+
auto witnessParamInfos = witnessUnsubstTy->getParameters();
7398+
7399+
// If we are transforming to a callee with an implicit param, drop the
7400+
// implicit param so that we can insert it again later. This ensures
7401+
// TranslateArguments does not need to know about this.
7402+
if (options.contains(ThunkGenFlag::CalleeHasImplicitIsolatedParam))
7403+
witnessParamInfos = witnessParamInfos.drop_front();
7404+
73827405
AbstractionPattern witnessOrigTy(witnessInfo.LoweredType);
7383-
TranslateArguments(*this, loc,
7384-
origParams, witnessParams,
7385-
witnessUnsubstTy, witnessUnsubstTy->getParameters())
7386-
.process(witnessOrigTy,
7387-
witnessSubstParams,
7388-
reqtOrigTy,
7389-
reqtSubstParams,
7390-
ignoreFinalInputOrigParam);
7406+
TranslateArguments(*this, loc, origParams, witnessParams, witnessUnsubstTy,
7407+
witnessParamInfos)
7408+
.process(witnessOrigTy, witnessSubstParams, reqtOrigTy, reqtSubstParams,
7409+
ignoreFinalInputOrigParam);
73917410

73927411
SILValue witnessFnRef = getWitnessFunctionRef(*this, witness,
73937412
origWitnessFTy,
@@ -7420,8 +7439,61 @@ void SILGenFunction::emitProtocolWitness(
74207439
}
74217440
}
74227441

7442+
// Now that we have translated arguments and inserted our thunk indirect
7443+
// parameters... before we forward those arguments, insert the implicit
7444+
// leading parameter.
7445+
if (options.contains(ThunkGenFlag::CalleeHasImplicitIsolatedParam)) {
7446+
auto reqtIsolation =
7447+
swift::getActorIsolation(requirement.getAbstractFunctionDecl());
7448+
switch (reqtIsolation) {
7449+
case ActorIsolation::Unspecified:
7450+
case ActorIsolation::Nonisolated:
7451+
case ActorIsolation::NonisolatedUnsafe:
7452+
args.push_back(emitNonIsolatedIsolation(loc).getValue());
7453+
break;
7454+
case ActorIsolation::Erased:
7455+
llvm::report_fatal_error("Found erased actor isolation?!");
7456+
break;
7457+
case ActorIsolation::GlobalActor: {
7458+
auto globalActor = reqtIsolation.getGlobalActor()->getCanonicalType();
7459+
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
7460+
break;
7461+
}
7462+
case ActorIsolation::ActorInstance:
7463+
case ActorIsolation::CallerIsolationInheriting: {
7464+
auto witnessIsolation =
7465+
swift::getActorIsolation(witness.getAbstractFunctionDecl());
7466+
switch (witnessIsolation) {
7467+
case ActorIsolation::Unspecified:
7468+
case ActorIsolation::Nonisolated:
7469+
case ActorIsolation::NonisolatedUnsafe:
7470+
args.push_back(emitNonIsolatedIsolation(loc).getValue());
7471+
break;
7472+
case ActorIsolation::Erased:
7473+
llvm::report_fatal_error("Found erased actor isolation?!");
7474+
break;
7475+
case ActorIsolation::GlobalActor: {
7476+
auto globalActor =
7477+
witnessIsolation.getGlobalActor()->getCanonicalType();
7478+
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
7479+
break;
7480+
}
7481+
case ActorIsolation::ActorInstance:
7482+
case ActorIsolation::CallerIsolationInheriting: {
7483+
auto isolatedArg = F.maybeGetIsolatedArgument();
7484+
assert(isolatedArg);
7485+
args.push_back(isolatedArg);
7486+
break;
7487+
}
7488+
}
7489+
break;
7490+
}
7491+
}
7492+
}
7493+
74237494
// - the rest of the arguments
7424-
forwardFunctionArguments(*this, loc, witnessFTy, witnessParams, args);
7495+
forwardFunctionArguments(*this, loc, witnessFTy, witnessParams, args,
7496+
options);
74257497

74267498
// Perform the call.
74277499
SILType witnessSILTy = SILType::getPrimitiveObjectType(witnessFTy);

0 commit comments

Comments
 (0)