Skip to content

Commit 2e9fffb

Browse files
committed
[SILGen] Implement actor isolation erasure thunk
The thunk is a reabstraction thunk with a custom prolog that has a runtime precondition check that makes sure that concurrent environment where the thunk is run matches that of a global actor associated with the thunked type.
1 parent 9d70c0b commit 2e9fffb

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,17 @@ RValue RValueEmitter::visitCovariantReturnConversionExpr(
21192119

21202120
RValue RValueEmitter::visitActorIsolationErasureExpr(ActorIsolationErasureExpr *E,
21212121
SGFContext C) {
2122-
llvm_unreachable("not implemented");
2122+
auto loc = SILLocation(E).asAutoGenerated();
2123+
auto funcRef = SGF.emitRValueAsSingleValue(E->getSubExpr());
2124+
2125+
auto isolatedType =
2126+
cast<AnyFunctionType>(E->getSubExpr()->getType()->getCanonicalType());
2127+
auto nonIsolatedType =
2128+
cast<AnyFunctionType>(E->getType()->getCanonicalType());
2129+
2130+
return RValue(SGF, E,
2131+
SGF.emitActorIsolationErasureThunk(loc, funcRef, isolatedType,
2132+
nonIsolatedType));
21232133
}
21242134

21252135
RValue RValueEmitter::visitErasureExpr(ErasureExpr *E, SGFContext C) {

lib/SILGen/SILGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,13 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
908908
/// new task.
909909
SILFunction *emitNativeAsyncToForeignThunk(SILDeclRef thunk);
910910

911+
/// Generates a thunk that contains a runtime precondition that
912+
/// the given function is called on the expected executor.
913+
ManagedValue emitActorIsolationErasureThunk(SILLocation loc,
914+
ManagedValue func,
915+
CanAnyFunctionType isolatedType,
916+
CanAnyFunctionType nonIsolatedType);
917+
911918
/// Generate a nullary function that returns the given value.
912919
/// If \p emitProfilerIncrement is set, emit a profiler increment for
913920
/// \p value.

lib/SILGen/SILGenPoly.cpp

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5228,7 +5228,9 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
52285228
CanAnyFunctionType inputSubstType,
52295229
AbstractionPattern outputOrigType,
52305230
CanAnyFunctionType outputSubstType,
5231-
CanType dynamicSelfType) {
5231+
CanType dynamicSelfType,
5232+
llvm::function_ref<void(SILGenFunction &)> emitProlog
5233+
= [](SILGenFunction &){}) {
52325234
PrettyStackTraceSILFunction stackTrace("emitting reabstraction thunk in",
52335235
&SGF.F);
52345236
auto thunkType = SGF.F.getLoweredFunctionType();
@@ -5258,6 +5260,8 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
52585260
}
52595261
}
52605262

5263+
emitProlog(SGF);
5264+
52615265
// Translate the argument values. Function parameters are
52625266
// contravariant: we want to switch the direction of transformation
52635267
// on them by flipping inputOrigType and outputOrigType.
@@ -7087,3 +7091,81 @@ void SILGenFunction::emitProtocolWitness(
70877091
// Now that we have finished emitting the function, verify it!
70887092
F.verify();
70897093
}
7094+
7095+
ManagedValue SILGenFunction::emitActorIsolationErasureThunk(
7096+
SILLocation loc, ManagedValue func,
7097+
CanAnyFunctionType isolatedType, CanAnyFunctionType nonIsolatedType) {
7098+
auto globalActor = isolatedType->getGlobalActor();
7099+
7100+
assert(globalActor);
7101+
assert(!nonIsolatedType->getGlobalActor());
7102+
7103+
CanSILFunctionType loweredIsolatedType =
7104+
func.getType().castTo<SILFunctionType>();
7105+
CanSILFunctionType loweredNonIsolatedType =
7106+
getLoweredType(nonIsolatedType).castTo<SILFunctionType>();
7107+
7108+
LLVM_DEBUG(
7109+
llvm::dbgs() << "=== Generating actor isolation erasure thunk for:";
7110+
loweredIsolatedType.dump(llvm::dbgs()); llvm::dbgs() << "\n");
7111+
7112+
if (loweredIsolatedType->getPatternSubstitutions()) {
7113+
loweredIsolatedType = loweredIsolatedType->getUnsubstitutedType(SGM.M);
7114+
func = B.createConvertFunction(
7115+
loc, func, SILType::getPrimitiveObjectType(loweredIsolatedType));
7116+
}
7117+
7118+
auto expectedType = loweredNonIsolatedType->getUnsubstitutedType(SGM.M);
7119+
7120+
SubstitutionMap interfaceSubs;
7121+
GenericEnvironment *genericEnv = nullptr;
7122+
CanType dynamicSelfType;
7123+
7124+
auto thunkType = buildThunkType(loweredIsolatedType,
7125+
expectedType,
7126+
isolatedType,
7127+
nonIsolatedType,
7128+
genericEnv,
7129+
interfaceSubs,
7130+
dynamicSelfType);
7131+
7132+
auto *thunk = SGM.getOrCreateReabstractionThunk(
7133+
thunkType, loweredIsolatedType, expectedType, dynamicSelfType,
7134+
globalActor->getCanonicalType());
7135+
7136+
if (thunk->empty()) {
7137+
thunk->setGenericEnvironment(genericEnv);
7138+
SILGenFunction thunkSGF(SGM, *thunk, FunctionDC);
7139+
7140+
buildThunkBody(
7141+
thunkSGF, loc, AbstractionPattern(isolatedType), isolatedType,
7142+
AbstractionPattern(nonIsolatedType), nonIsolatedType, dynamicSelfType,
7143+
[&loc, &globalActor](SILGenFunction &thunkSGF) {
7144+
auto expectedExecutor =
7145+
thunkSGF.emitLoadGlobalActorExecutor(globalActor);
7146+
thunkSGF.emitPreconditionCheckExpectedExecutor(loc, expectedExecutor);
7147+
});
7148+
7149+
SGM.emitLazyConformancesForFunction(thunk);
7150+
}
7151+
7152+
// Create it in the current function.
7153+
ManagedValue thunkedFn = createPartialApplyOfThunk(
7154+
*this, loc, thunk, interfaceSubs, dynamicSelfType, loweredNonIsolatedType,
7155+
func.ensurePlusOne(*this, loc));
7156+
7157+
if (expectedType != loweredNonIsolatedType) {
7158+
auto escapingExpectedType = loweredNonIsolatedType->getWithExtInfo(
7159+
loweredNonIsolatedType->getExtInfo().withNoEscape(false));
7160+
thunkedFn = B.createConvertFunction(
7161+
loc, thunkedFn, SILType::getPrimitiveObjectType(escapingExpectedType));
7162+
}
7163+
7164+
if (loweredIsolatedType->isNoEscape()) {
7165+
thunkedFn = B.createConvertEscapeToNoEscape(
7166+
loc, thunkedFn,
7167+
SILType::getPrimitiveObjectType(loweredNonIsolatedType));
7168+
}
7169+
7170+
return thunkedFn;
7171+
}

0 commit comments

Comments
 (0)