mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
38
include/swift/SIL/ConcurrencyUtils.h
Normal file
38
include/swift/SIL/ConcurrencyUtils.h
Normal 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
|
||||
@@ -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());
|
||||
|
||||
@@ -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*/);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,6 +2,7 @@ target_sources(swiftSIL PRIVATE
|
||||
BasicBlockUtils.cpp
|
||||
BitDataflow.cpp
|
||||
CalleeCache.cpp
|
||||
ConcurrencyUtils.cpp
|
||||
DebugUtils.cpp
|
||||
Dominance.cpp
|
||||
DynamicCasts.cpp
|
||||
|
||||
32
lib/SIL/Utils/ConcurrencyUtils.cpp
Normal file
32
lib/SIL/Utils/ConcurrencyUtils.cpp
Normal 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;
|
||||
}
|
||||
70
lib/SILGen/ConcurrencyUtils.h
Normal file
70
lib/SILGen/ConcurrencyUtils.h
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user