[silgen] Use Builtin.ImplicitActor instead of Optional<any Actor> to represent the implicit isolated parameter.

NOTE: We are not performing any bitmasking at all now. This is so that we can
transition the code base/tests to expect Builtin.ImplicitActor instead
of Optional<any Actor>.

NOTE: The actual test changes are in the next commit. I did this to make it
easier to review the changes.

This should not have any user visible changes.

(cherry picked from commit 788abd0b96)
This commit is contained in:
Michael Gottesman
2025-08-06 17:01:52 -07:00
parent f625cce668
commit ce162afd9d
16 changed files with 360 additions and 102 deletions

View File

@@ -0,0 +1,38 @@
//===--- ConcurrencyUtils.h -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_CONCURRENCYUTILS_H
#define SWIFT_SIL_CONCURRENCYUTILS_H
#include "swift/SIL/SILType.h"
namespace swift {
class SILValue;
class SILBuilder;
class SILLocation;
/// Clear the implicit isolated bits of value.
///
/// \p value must be Builtin.ImplicitActor
///
/// \p finalType if empty, we always return
/// Builtin.ImplicitActor. Otherwise we bitcast to finalType after
/// tieing the lifetime of the result to \p value.
SILValue clearImplicitActorBits(SILBuilder &b, SILLocation loc, SILValue value,
SILType finalType = {});
SILValue setImplicitActorBits(SILBuilder &b, SILLocation loc, SILValue value);
} // namespace swift
#endif

View File

@@ -1337,6 +1337,17 @@ public:
forwardingOwnershipKind));
}
/// Create an unchecked_value_cast when Ownership SSA is enabled and
/// unchecked_bitwise_cast otherwise.
///
/// Intended to be used in utility code that needs to support both Ownership
/// SSA and non-Ownership SSA code.
SILValue emitUncheckedValueCast(SILLocation loc, SILValue op, SILType ty) {
if (hasOwnership())
return createUncheckedValueCast(loc, op, ty);
return createUncheckedBitwiseCast(loc, op, ty);
}
RefToBridgeObjectInst *createRefToBridgeObject(SILLocation Loc, SILValue Ref,
SILValue Bits) {
return createRefToBridgeObject(Loc, Ref, Bits, Ref->getOwnershipKind());

View File

@@ -1715,11 +1715,7 @@ private:
// implicit isolation parameter.
if (IsolationInfo && IsolationInfo->isCallerIsolationInheriting() &&
Convs.hasCallerIsolationParameter()) {
auto actorProtocol = TC.Context.getProtocol(KnownProtocolKind::Actor);
auto actorType =
ExistentialType::get(actorProtocol->getDeclaredInterfaceType());
addParameter(-1,
CanType(actorType).wrapInOptionalType(),
addParameter(-1, CanType(TC.Context.TheImplicitActorType),
ParameterConvention::Direct_Guaranteed,
ParameterTypeFlags().withIsolated(true),
true /*implicit leading parameter*/);

View File

@@ -2393,6 +2393,19 @@ namespace {
UnsafeValueBufferTypeLowering(silType, Expansion, isSensitive);
}
TypeLowering *
visitBuiltinImplicitActorType(CanBuiltinImplicitActorType type,
AbstractionPattern origType,
IsTypeExpansionSensitive_t isSensitive) {
auto silType = SILType::getPrimitiveObjectType(type);
auto properties = SILTypeProperties();
properties.setTypeExpansionSensitive(isSensitive);
properties.setNonTrivial();
properties.setLexical(IsLexical);
return new (TC)
MiscNontrivialTypeLowering(silType, properties, Expansion);
}
TypeLowering *visitPackType(CanPackType packType,
AbstractionPattern origType,
IsTypeExpansionSensitive_t isSensitive) {

View File

@@ -2,6 +2,7 @@ target_sources(swiftSIL PRIVATE
BasicBlockUtils.cpp
BitDataflow.cpp
CalleeCache.cpp
ConcurrencyUtils.cpp
DebugUtils.cpp
Dominance.cpp
DynamicCasts.cpp

View File

@@ -0,0 +1,32 @@
//===--- ConcurrencyUtils.cpp ---------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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/SIL/ConcurrencyUtils.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILLocation.h"
using namespace swift;
SILValue swift::clearImplicitActorBits(SILBuilder &b, SILLocation loc,
SILValue value, SILType finalType) {
if (!finalType)
finalType = SILType::getBuiltinImplicitActorType(b.getASTContext());
if (value->getType() == finalType)
return value;
return b.emitUncheckedValueCast(loc, value, finalType);
}
SILValue swift::setImplicitActorBits(SILBuilder &b, SILLocation loc,
SILValue value) {
return value;
}

View File

@@ -0,0 +1,70 @@
//===--- ConcurrencyUtils.h -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILGEN_CONCURRENCYUTILS_H
#define SWIFT_SILGEN_CONCURRENCYUTILS_H
#include "RValue.h"
#include "SILGenFunction.h"
#include "swift/SIL/ConcurrencyUtils.h"
namespace swift {
class SILLocation;
class Expr;
namespace Lowering {
class SILGenFunction;
class RValue;
class ManagedValue;
inline ManagedValue clearImplicitActorBits(SILGenFunction &SGF, SILLocation loc,
ManagedValue implicitIsolatedActor,
SILType type = {}) {
return ManagedValue::forBorrowedRValue(clearImplicitActorBits(
SGF.B, loc, implicitIsolatedActor.getUnmanagedValue(), type));
}
/// Clear the TBI bits if AArch64HasTBI is set. Otherwise clear the low tagged
/// bits.
///
/// \param expr - the expression which yielded this r-value; its type
/// will become the substituted formal type of this r-value
/// \param implicitIsolatedActor should be an Optional<any Actor>.
inline RValue clearImplicitActorBits(SILGenFunction &SGF, Expr *expr,
ManagedValue implicitIsolatedActor,
SILType type = {}) {
return RValue(SGF, expr,
clearImplicitActorBits(SGF, SILLocation(expr),
implicitIsolatedActor, type));
}
inline ManagedValue setImplicitActorBits(SILGenFunction &SGF, SILLocation loc,
ManagedValue implicitIsolatedActor) {
return ManagedValue::forBorrowedRValue(setImplicitActorBits(
SGF.B, loc, implicitIsolatedActor.getUnmanagedValue()));
}
inline RValue setImplicitActorBits(SILGenFunction &SGF, Expr *expr,
ManagedValue implicitIsolatedActor) {
return RValue(
SGF, expr,
setImplicitActorBits(SGF, SILLocation(expr), implicitIsolatedActor));
}
} // namespace Lowering
} // namespace swift
#endif

View File

@@ -13,6 +13,7 @@
#include "ArgumentScope.h"
#include "ArgumentSource.h"
#include "Callee.h"
#include "ConcurrencyUtils.h"
#include "Conversion.h"
#include "ExecutorBreadcrumb.h"
#include "FormalEvaluation.h"
@@ -5860,8 +5861,12 @@ ApplyOptions CallEmission::emitArgumentsForNormalApply(
args.push_back({});
// NOTE: Even though this calls emitActorInstanceIsolation, this also
// handles glboal actor isolated cases.
args.back().push_back(SGF.emitActorInstanceIsolation(
callSite->Loc, executor, executor.getType().getASTType()));
auto erasedActor =
SGF.emitActorInstanceIsolation(callSite->Loc, executor,
executor.getType().getASTType())
.borrow(SGF, callSite->Loc);
args.back().push_back(
SGF.B.convertToImplicitActor(callSite->Loc, erasedActor));
}
uncurriedLoc = callSite->Loc;

View File

@@ -1667,23 +1667,22 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
isolatedParameter && isolatedParameter->hasOption(SILParameterInfo::ImplicitLeading)) {
assert(F.isAsync() && "Can only be async");
assert(isolation && "No isolation?!");
switch (isolation->getKind()) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
case ActorIsolation::CallerIsolationInheriting:
args.push_back(emitNonIsolatedIsolation(loc).getValue());
break;
case ActorIsolation::ActorInstance:
llvm::report_fatal_error("Should never see this");
break;
case ActorIsolation::GlobalActor:
args.push_back(emitLoadGlobalActorExecutor(isolation->getGlobalActor()));
break;
case ActorIsolation::Erased:
llvm::report_fatal_error("Should never see this");
break;
}
auto value = [&]() -> SILValue {
switch (isolation->getKind()) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
case ActorIsolation::CallerIsolationInheriting:
return emitNonIsolatedIsolation(loc).getValue();
case ActorIsolation::ActorInstance:
llvm::report_fatal_error("Should never see this");
case ActorIsolation::GlobalActor:
return emitLoadGlobalActorExecutor(isolation->getGlobalActor());
case ActorIsolation::Erased:
llvm::report_fatal_error("Should never see this");
}
}();
args.push_back(B.convertToImplicitActor(loc, value));
}
// Bridge the arguments.

View File

@@ -1244,3 +1244,16 @@ ManagedValue SILGenBuilder::borrowObjectRValue(SILGenFunction &SGF,
}
return SGF.emitFormalEvaluationManagedBeginBorrow(loc, value);
}
SILValue SILGenBuilder::convertToImplicitActor(SILLocation loc,
SILValue value) {
auto type = SILType::getBuiltinImplicitActorType(getASTContext());
if (value->getType() == type)
return value;
assert(value->getType() == SILType::getOpaqueIsolationType(getASTContext()) &&
"Can only convert Optional<any Actor> to "
"Builtin.ImplicitActor");
if (value->getOwnershipKind() != OwnershipKind::Guaranteed)
value = SGF.emitManagedBeginBorrow(loc, value).getValue();
return createUncheckedValueCast(loc, value, type);
}

View File

@@ -551,6 +551,17 @@ public:
createTupleAddrConstructor(loc, destAddr, values, isInitOfDest);
}
SILValue convertToImplicitActor(SILLocation loc, SILValue value);
ManagedValue convertToImplicitActor(SILLocation loc, ManagedValue value) {
auto type = SILType::getBuiltinImplicitActorType(getASTContext());
if (value.getType() == type)
return value;
SILValue result =
convertToImplicitActor(loc, value.borrow(SGF, loc).getValue());
return ManagedValue::forBorrowedRValue(result);
}
};
} // namespace Lowering

View File

@@ -425,6 +425,10 @@ emitNonOptionalActorInstanceIsolation(SILGenFunction &SGF, SILLocation loc,
if (actor.getType() == anyActorTy)
return actor;
if (actor.getType() ==
SILType::getBuiltinImplicitActorType(SGF.getASTContext()))
return actor;
CanType anyActorType = anyActorTy.getASTType();
// If the actor is a distributed actor, (1) it had better be local
@@ -449,6 +453,10 @@ SILGenFunction::emitActorInstanceIsolation(SILLocation loc, ManagedValue actor,
return actor;
}
// If we started with a Builtin.ImplicitActor, we're done.
if (actorType == getASTContext().TheImplicitActorType->getCanonicalType())
return actor;
// Otherwise, if we have an optional value, we need to transform the payload.
auto actorObjectType = actorType.getOptionalObjectType();
if (actorObjectType) {

View File

@@ -954,7 +954,7 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
if (F.isNonisolatedNonsending()) {
auto paramTy = F.mapTypeIntoContext(
SILType::getOpaqueIsolationType(F.getASTContext()));
SILType::getBuiltinImplicitActorType(F.getASTContext()));
auto inContextParamTy = F.getLoweredType(paramTy.getASTType())
.getCategoryType(paramTy.getCategory());
SILArgument *arg = F.begin()->createFunctionArgument(inContextParamTy);

View File

@@ -13,6 +13,7 @@
#include "ArgumentScope.h"
#include "ArgumentSource.h"
#include "Callee.h"
#include "ConcurrencyUtils.h"
#include "Condition.h"
#include "Conversion.h"
#include "Initialization.h"
@@ -7319,13 +7320,10 @@ RValue RValueEmitter::visitCurrentContextIsolationExpr(
auto *isolatedArg = SGF.F.maybeGetIsolatedArgument();
assert(isolatedArg &&
"Caller Isolation Inheriting without isolated parameter");
ManagedValue isolatedMV;
if (isolatedArg->getOwnershipKind() == OwnershipKind::Guaranteed) {
isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
} else {
isolatedMV = ManagedValue::forUnmanagedOwnedValue(isolatedArg);
}
return RValue(SGF, E, isolatedMV);
auto isolatedMV = ManagedValue::forBorrowedRValue(isolatedArg);
return clearImplicitActorBits(
SGF, E, isolatedMV,
SILType::getOpaqueIsolationType(SGF.getASTContext()));
}
if (isolation == ActorIsolation::ActorInstance) {

View File

@@ -5669,7 +5669,8 @@ static void buildThunkBody(SILGenFunction &SGF, SILLocation loc,
assert(forwardedIsolationValue);
SGF.B.createHopToExecutor(loc, forwardedIsolationValue, false);
argValues.push_back(forwardedIsolationValue);
argValues.push_back(
SGF.B.convertToImplicitActor(loc, forwardedIsolationValue));
}
// Add the rest of the arguments.
@@ -7122,49 +7123,47 @@ SILGenFunction::emitVTableThunk(SILDeclRef base,
return *derivedIsolationCache;
};
switch (baseIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
args.push_back(emitNonIsolatedIsolation(loc).getValue());
break;
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
break;
case ActorIsolation::GlobalActor: {
auto globalActor = baseIsolation.getGlobalActor()->getCanonicalType();
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
break;
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto derivedIsolation = getDerivedIsolation();
switch (derivedIsolation) {
auto arg = [&]() -> SILValue {
switch (baseIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
args.push_back(emitNonIsolatedIsolation(loc).getValue());
break;
return emitNonIsolatedIsolation(loc).getValue();
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
break;
return SILValue();
case ActorIsolation::GlobalActor: {
auto globalActor =
derivedIsolation.getGlobalActor()->getCanonicalType();
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
break;
auto globalActor = baseIsolation.getGlobalActor()->getCanonicalType();
return emitGlobalActorIsolation(loc, globalActor).getValue();
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto isolatedArg = F.maybeGetIsolatedArgument();
assert(isolatedArg);
args.push_back(isolatedArg);
break;
auto derivedIsolation = getDerivedIsolation();
switch (derivedIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
return emitNonIsolatedIsolation(loc).getValue();
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
return SILValue();
case ActorIsolation::GlobalActor: {
auto globalActor =
derivedIsolation.getGlobalActor()->getCanonicalType();
return emitGlobalActorIsolation(loc, globalActor).getValue();
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto isolatedArg = F.maybeGetIsolatedArgument();
assert(isolatedArg);
return isolatedArg;
}
}
}
}
break;
}
}
}();
args.push_back(B.convertToImplicitActor(loc, arg));
// If our derived isolation is caller isolation inheriting and our base
// isn't, we need to insert a hop so that derived can assume that it does
@@ -7626,49 +7625,47 @@ void SILGenFunction::emitProtocolWitness(
}
return *witnessIsolationCache;
};
switch (reqtIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
args.push_back(emitNonIsolatedIsolation(loc).getValue());
break;
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
break;
case ActorIsolation::GlobalActor: {
auto globalActor = reqtIsolation.getGlobalActor()->getCanonicalType();
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
break;
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto witnessIsolation = getWitnessIsolation();
switch (witnessIsolation) {
auto arg = [&]() -> SILValue {
switch (reqtIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
args.push_back(emitNonIsolatedIsolation(loc).getValue());
break;
return emitNonIsolatedIsolation(loc).getValue();
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
break;
return SILValue();
case ActorIsolation::GlobalActor: {
auto globalActor =
witnessIsolation.getGlobalActor()->getCanonicalType();
args.push_back(emitGlobalActorIsolation(loc, globalActor).getValue());
break;
auto globalActor = reqtIsolation.getGlobalActor()->getCanonicalType();
return emitGlobalActorIsolation(loc, globalActor).getValue();
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto isolatedArg = F.maybeGetIsolatedArgument();
assert(isolatedArg);
args.push_back(isolatedArg);
break;
auto witnessIsolation = getWitnessIsolation();
switch (witnessIsolation) {
case ActorIsolation::Unspecified:
case ActorIsolation::Nonisolated:
case ActorIsolation::NonisolatedUnsafe:
return emitNonIsolatedIsolation(loc).getValue();
case ActorIsolation::Erased:
llvm::report_fatal_error("Found erased actor isolation?!");
return SILValue();
case ActorIsolation::GlobalActor: {
auto globalActor =
witnessIsolation.getGlobalActor()->getCanonicalType();
return emitGlobalActorIsolation(loc, globalActor).getValue();
}
case ActorIsolation::ActorInstance:
case ActorIsolation::CallerIsolationInheriting: {
auto isolatedArg = F.maybeGetIsolatedArgument();
assert(isolatedArg);
return isolatedArg;
}
}
}
}
break;
}
}
}();
args.push_back(B.convertToImplicitActor(loc, arg));
// If our reqtIsolation was not caller isolation inheriting, but our witness
// isolation is caller isolation inheriting, hop onto the reqtIsolation so

View File

@@ -11,15 +11,17 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "insert-hop-to-executor"
#include "swift/AST/ConformanceLookup.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/FrozenMultiMap.h"
#include "swift/SIL/ConcurrencyUtils.h"
#include "swift/SIL/Dominance.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/Dominance.h"
#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "llvm/ADT/ScopedHashTable.h"
using namespace swift;
@@ -52,6 +54,7 @@ namespace {
/// IRGen expects hops to be to executors before it runs.
class LowerHopToActor {
DominanceInfo *Dominance;
SILOptFunctionBuilder &FuncBuilder;
/// A map from an actor value to the dominating instruction that
/// will derive the executor.
@@ -71,7 +74,8 @@ class LowerHopToActor {
SILValue actor, bool makeOptional);
public:
LowerHopToActor(DominanceInfo *dominance) : Dominance(dominance) {}
LowerHopToActor(DominanceInfo *dominance, SILOptFunctionBuilder &funcBuilder)
: Dominance(dominance), FuncBuilder(funcBuilder) {}
/// The entry point to the transformation.
bool run();
@@ -301,6 +305,65 @@ static SILValue getExecutorForOptionalActor(SILBuilder &B, SILLocation loc,
return result;
}
static SILValue getExecutorForImplicitActor(SILOptFunctionBuilder &funcBuilder,
SILBuilderWithScope &parentBuilder,
SILLocation loc, SILValue actor) {
auto &ctx = parentBuilder.getASTContext();
// First create our parameter infos. Our params are @guaranteed @isolated
// @leading Builtin.ImplicitActor.
auto implicitIsolatedActorType = SILType::getBuiltinImplicitActorType(ctx);
SmallVector<SILParameterInfo, 1> parameterInfo;
parameterInfo.push_back(SILParameterInfo(
implicitIsolatedActorType.getASTType(),
ParameterConvention::Direct_Guaranteed,
{SILParameterInfo::ImplicitLeading, SILParameterInfo::Isolated}));
// Then create our result types. Our result is Optional<Builtin.Executor>.
auto executorType = SILType::getPrimitiveObjectType(ctx.TheExecutorType);
auto optionalExecutorType = SILType::getOptionalType(executorType);
SmallVector<SILResultInfo, 1> resultInfo;
resultInfo.push_back(SILResultInfo(optionalExecutorType.getASTType(),
ResultConvention::Unowned));
// Then use that to create our function type and SILFunction. We purposely use
// a shared function so we can take advantage of linkonce_odr.
auto autoGenLoc = RegularLocation::getAutoGeneratedLocation();
CanSILFunctionType funcType = SILFunctionType::get(
nullptr, SILFunctionType::ExtInfo::getThin(), SILCoroutineKind::None,
ParameterConvention::Direct_Unowned, parameterInfo, {}, resultInfo, {},
{}, {}, ctx);
auto *newFunc = funcBuilder.getOrCreateSharedFunction(
autoGenLoc, "_swift_implicitisolationactor_to_executor_cast", funcType,
IsNotBare, IsNotTransparent, IsNotSerialized, ProfileCounter(),
IsNotThunk, IsNotDynamic, IsNotDistributed, IsNotRuntimeAccessible);
// If our function does not yet have a body... create that body.
//
// Our body is just a concatenation of clearing the implicit isolated actor
// bits + cast to Optional<any Actor> + getExecutorForOptionalActor.
if (newFunc->empty()) {
// First turn off ownership.
newFunc->setOwnershipEliminated();
// Turn off inlining. This is a helper function to reduce code-size. We are
// too late for SIL to inline... but we want to also prevent LLVM from
// inlining as well.
newFunc->setInlineStrategy(Inline_t::NoInline);
auto *front = newFunc->createBasicBlock();
SILBuilder builder(front);
auto *fArg = front->createFunctionArgument(implicitIsolatedActorType);
auto value = clearImplicitActorBits(builder, autoGenLoc, fArg,
SILType::getOpaqueIsolationType(ctx));
value = getExecutorForOptionalActor(builder, autoGenLoc, value);
builder.createReturn(autoGenLoc, value);
}
// Then create the apply that calls our helper.
auto *funcRef = parentBuilder.createFunctionRef(loc, newFunc);
return parentBuilder.createApply(loc, funcRef, SubstitutionMap(), {actor});
}
SILValue LowerHopToActor::emitGetExecutor(SILBuilderWithScope &B,
SILLocation loc, SILValue actor,
bool makeOptional) {
@@ -317,7 +380,9 @@ SILValue LowerHopToActor::emitGetExecutor(SILBuilderWithScope &B,
bool needEndBorrow = false;
SILValue unmarkedExecutor;
if (auto wrappedActor = actorType->getOptionalObjectType()) {
if (actorType == B.getASTContext().TheImplicitActorType) {
unmarkedExecutor = getExecutorForImplicitActor(FuncBuilder, B, loc, actor);
} else if (auto wrappedActor = actorType->getOptionalObjectType()) {
assert(makeOptional);
if (B.hasOwnership() &&
actor->getOwnershipKind() != OwnershipKind::Guaranteed) {
@@ -355,7 +420,8 @@ class LowerHopToActorPass : public SILFunctionTransform {
void run() override {
auto fn = getFunction();
auto domTree = getAnalysis<DominanceAnalysis>()->get(fn);
LowerHopToActor pass(domTree);
SILOptFunctionBuilder funcBuilder(*this);
LowerHopToActor pass(domTree, funcBuilder);
if (pass.run())
invalidateAnalysis(SILAnalysis::InvalidationKind::BranchesAndInstructions);
}