Skip to content

Commit 443489f

Browse files
authored
Merge pull request swiftlang#71152 from rjmccall/centralize-function-type-isolation
Create a uniform representation for function type isolation
2 parents 1703367 + b0fb03d commit 443489f

25 files changed

+448
-153
lines changed

include/swift/AST/ASTDemangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class ASTBuilder {
143143

144144
Type createFunctionType(
145145
ArrayRef<Demangle::FunctionParam<Type>> params,
146-
Type output, FunctionTypeFlags flags,
146+
Type output, FunctionTypeFlags flags, ExtendedFunctionTypeFlags extFlags,
147147
FunctionMetadataDifferentiabilityKind diffKind, Type globalActor,
148148
Type thrownError);
149149

include/swift/AST/ExtInfo.h

Lines changed: 138 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,78 @@ enum class SILFunctionTypeRepresentation : uint8_t;
4747

4848
namespace swift {
4949

50+
/// The formal isolation of a function type.
51+
class FunctionTypeIsolation {
52+
public:
53+
enum class Kind : uint8_t {
54+
/// The function is not isolated.
55+
NonIsolated,
56+
57+
/// The function is isolated to a global actor.
58+
GlobalActor,
59+
60+
/// The function has an isolated parameter; which one is indicated in
61+
/// the parameter list.
62+
Parameter,
63+
64+
/// The function is dynamically isolated.
65+
Dynamic,
66+
};
67+
68+
static constexpr size_t NumBits = 3; // future-proof this slightly
69+
static constexpr size_t Mask = (1 << NumBits) - 1;
70+
71+
private:
72+
llvm::PointerIntPair<Type, NumBits, Kind> value;
73+
74+
FunctionTypeIsolation(Kind kind, Type type = Type()) : value(type, kind) {}
75+
76+
public:
77+
static FunctionTypeIsolation forNonIsolated() {
78+
return { Kind::NonIsolated };
79+
}
80+
static FunctionTypeIsolation forGlobalActor(Type type) {
81+
assert(type && "creating global actor isolation without an actor type");
82+
return { Kind::GlobalActor, type };
83+
}
84+
static FunctionTypeIsolation forParameter() {
85+
return { Kind::Parameter };
86+
}
87+
static FunctionTypeIsolation forDynamic() {
88+
return { Kind::Dynamic };
89+
}
90+
91+
Kind getKind() const { return value.getInt(); }
92+
bool isNonIsolated() const {
93+
return getKind() == Kind::NonIsolated;
94+
}
95+
bool isGlobalActor() const {
96+
return getKind() == Kind::GlobalActor;
97+
}
98+
Type getGlobalActorType() const {
99+
assert(getKind() == Kind::GlobalActor);
100+
return value.getPointer();
101+
}
102+
bool isParameter() const {
103+
return getKind() == Kind::Parameter;
104+
}
105+
bool isDynamic() const {
106+
return getKind() == Kind::Dynamic;
107+
}
108+
109+
// The opaque accessors below are just for the benefit of ExtInfoBuilder,
110+
// which finds it convenient to break down the type separately. Normal
111+
// clients should use the accessors above.
112+
113+
Type getOpaqueType() const {
114+
return value.getPointer();
115+
}
116+
117+
static FunctionTypeIsolation fromOpaqueValues(Kind kind, Type type) {
118+
return FunctionTypeIsolation(kind, type);
119+
}
120+
};
121+
50122
// MARK: - ClangTypeInfo
51123
/// Wrapper class for storing a clang::Type in an (AST|SIL)ExtInfo.
52124
class ClangTypeInfo {
@@ -373,20 +445,24 @@ class ASTExtInfoBuilder {
373445
// If bits are added or removed, then TypeBase::NumAFTExtInfoBits
374446
// and NumMaskBits must be updated, and they must match.
375447
//
376-
// |representation|noEscape|concurrent|async|throws|differentiability|
377-
// | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 |
448+
// |representation|noEscape|concurrent|async|throws|isolation|differentiability|
449+
// | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 | 11 .. 13 |
378450
//
379451
enum : unsigned {
380452
RepresentationMask = 0xF << 0,
381453
NoEscapeMask = 1 << 4,
382454
SendableMask = 1 << 5,
383455
AsyncMask = 1 << 6,
384456
ThrowsMask = 1 << 7,
385-
DifferentiabilityMaskOffset = 8,
457+
IsolationMaskOffset = 8,
458+
IsolationMask = 0x7 << IsolationMaskOffset,
459+
DifferentiabilityMaskOffset = 11,
386460
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
387-
NumMaskBits = 11
461+
NumMaskBits = 14
388462
};
389463

464+
static_assert(FunctionTypeIsolation::Mask == 0x7, "update mask manually");
465+
390466
unsigned bits; // Naturally sized for speed.
391467

392468
ClangTypeInfo clangTypeInfo;
@@ -403,33 +479,39 @@ class ASTExtInfoBuilder {
403479
LifetimeDependenceInfo lifetimeDependenceInfo)
404480
: bits(bits), clangTypeInfo(clangTypeInfo), globalActor(globalActor),
405481
thrownError(thrownError),
406-
lifetimeDependenceInfo(lifetimeDependenceInfo) {}
482+
lifetimeDependenceInfo(lifetimeDependenceInfo) {
483+
assert(isThrowing() || !thrownError);
484+
assert(hasGlobalActorFromBits(bits) == !globalActor.isNull());
485+
}
407486

408487
public:
409488
/// An ExtInfoBuilder for a typical Swift function: @convention(swift),
410489
/// @escaping, non-throwing, non-differentiable.
411490
ASTExtInfoBuilder()
412491
: ASTExtInfoBuilder(Representation::Swift, false, false, Type(),
413492
DifferentiabilityKind::NonDifferentiable, nullptr,
414-
Type(), LifetimeDependenceInfo()) {}
493+
FunctionTypeIsolation::forNonIsolated(),
494+
LifetimeDependenceInfo()) {}
415495

416496
// Constructor for polymorphic type.
417497
ASTExtInfoBuilder(Representation rep, bool throws, Type thrownError)
418498
: ASTExtInfoBuilder(rep, false, throws, thrownError,
419499
DifferentiabilityKind::NonDifferentiable, nullptr,
420-
Type(), LifetimeDependenceInfo()) {}
500+
FunctionTypeIsolation::forNonIsolated(),
501+
LifetimeDependenceInfo()) {}
421502

422503
// Constructor with no defaults.
423504
ASTExtInfoBuilder(Representation rep, bool isNoEscape, bool throws,
424505
Type thrownError, DifferentiabilityKind diffKind,
425-
const clang::Type *type, Type globalActor,
506+
const clang::Type *type, FunctionTypeIsolation isolation,
426507
LifetimeDependenceInfo lifetimeDependenceInfo)
427508
: ASTExtInfoBuilder(
428509
((unsigned)rep) | (isNoEscape ? NoEscapeMask : 0) |
429510
(throws ? ThrowsMask : 0) |
430511
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
431-
DifferentiabilityMask),
432-
ClangTypeInfo(type), globalActor, thrownError,
512+
DifferentiabilityMask) |
513+
(unsigned(isolation.getKind()) << IsolationMaskOffset),
514+
ClangTypeInfo(type), isolation.getOpaqueType(), thrownError,
433515
lifetimeDependenceInfo) {}
434516

435517
void checkInvariants() const;
@@ -474,6 +556,26 @@ class ASTExtInfoBuilder {
474556
return lifetimeDependenceInfo;
475557
}
476558

559+
FunctionTypeIsolation::Kind getIsolationKind() const {
560+
return getIsolationKindFromBits(bits);
561+
}
562+
static FunctionTypeIsolation::Kind getIsolationKindFromBits(unsigned bits) {
563+
return FunctionTypeIsolation::Kind(
564+
(bits & IsolationMask) >> IsolationMaskOffset);
565+
}
566+
bool isDynamicallyIsolated() const {
567+
return getIsolationKind() == FunctionTypeIsolation::Kind::Dynamic;
568+
}
569+
static bool hasGlobalActorFromBits(unsigned bits) {
570+
return getIsolationKindFromBits(bits)
571+
== FunctionTypeIsolation::Kind::GlobalActor;
572+
}
573+
574+
FunctionTypeIsolation getIsolation() const {
575+
return FunctionTypeIsolation::fromOpaqueValues(getIsolationKind(),
576+
globalActor);
577+
}
578+
477579
constexpr bool hasSelfParam() const {
478580
switch (getSILRepresentation()) {
479581
case SILFunctionTypeRepresentation::Thick:
@@ -529,6 +631,7 @@ class ASTExtInfoBuilder {
529631
}
530632
[[nodiscard]]
531633
ASTExtInfoBuilder withThrows(bool throws, Type thrownError) const {
634+
assert(throws || !thrownError);
532635
return ASTExtInfoBuilder(
533636
throws ? (bits | ThrowsMask) : (bits & ~ThrowsMask), clangTypeInfo,
534637
globalActor, thrownError, lifetimeDependenceInfo);
@@ -566,15 +669,19 @@ class ASTExtInfoBuilder {
566669
}
567670

568671
[[nodiscard]]
569-
ASTExtInfoBuilder withGlobalActor(Type globalActor) const {
672+
ASTExtInfoBuilder withLifetimeDependenceInfo(
673+
LifetimeDependenceInfo lifetimeDependenceInfo) const {
570674
return ASTExtInfoBuilder(bits, clangTypeInfo, globalActor, thrownError,
571675
lifetimeDependenceInfo);
572676
}
573677

574-
[[nodiscard]] ASTExtInfoBuilder withLifetimeDependenceInfo(
575-
LifetimeDependenceInfo lifetimeDependenceInfo) const {
576-
return ASTExtInfoBuilder(bits, clangTypeInfo, globalActor, thrownError,
577-
lifetimeDependenceInfo);
678+
[[nodiscard]]
679+
ASTExtInfoBuilder withIsolation(FunctionTypeIsolation isolation) const {
680+
return ASTExtInfoBuilder(
681+
(bits & ~IsolationMask)
682+
| (unsigned(isolation.getKind()) << IsolationMaskOffset),
683+
clangTypeInfo, isolation.getOpaqueType(), thrownError,
684+
lifetimeDependenceInfo);
578685
}
579686

580687
bool isEqualTo(ASTExtInfoBuilder other, bool useClangTypes) const {
@@ -664,6 +771,8 @@ class ASTExtInfo {
664771
return builder.getLifetimeDependenceInfo();
665772
}
666773

774+
FunctionTypeIsolation getIsolation() const { return builder.getIsolation(); }
775+
667776
/// Helper method for changing the representation.
668777
///
669778
/// Prefer using \c ASTExtInfoBuilder::withRepresentation for chaining.
@@ -712,9 +821,22 @@ class ASTExtInfo {
712821
return builder.withAsync(async).build();
713822
}
714823

824+
[[nodiscard]]
825+
ASTExtInfo withIsolation(FunctionTypeIsolation isolation) const {
826+
return builder.withIsolation(isolation).build();
827+
}
828+
829+
[[nodiscard]]
830+
ASTExtInfo withoutIsolation() const {
831+
return builder.withIsolation(FunctionTypeIsolation::forNonIsolated())
832+
.build();
833+
}
834+
715835
[[nodiscard]]
716836
ASTExtInfo withGlobalActor(Type globalActor) const {
717-
return builder.withGlobalActor(globalActor).build();
837+
return builder.withIsolation(
838+
FunctionTypeIsolation::forGlobalActor(globalActor))
839+
.build();
718840
}
719841

720842
[[nodiscard]] ASTExtInfo withLifetimeDependenceInfo(

include/swift/AST/Types.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
384384
}
385385

386386
protected:
387-
enum { NumAFTExtInfoBits = 11 };
387+
enum { NumAFTExtInfoBits = 14 };
388388
enum { NumSILExtInfoBits = 13 };
389389

390390
// clang-format off
@@ -412,13 +412,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
412412

413413
SWIFT_INLINE_BITFIELD_EMPTY(ParenType, SugarType);
414414

415-
SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+1+1+1+16,
415+
SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+1+1+16,
416416
/// Extra information which affects how the function is called, like
417417
/// regparm and the calling convention.
418418
ExtInfoBits : NumAFTExtInfoBits,
419419
HasExtInfo : 1,
420420
HasClangTypeInfo : 1,
421-
HasGlobalActor : 1,
422421
HasThrownError : 1,
423422
HasLifetimeDependenceInfo : 1,
424423
: NumPadBits,
@@ -3365,10 +3364,9 @@ class AnyFunctionType : public TypeBase {
33653364
Bits.AnyFunctionType.ExtInfoBits = Info.value().getBits();
33663365
Bits.AnyFunctionType.HasClangTypeInfo =
33673366
!Info.value().getClangTypeInfo().empty();
3368-
Bits.AnyFunctionType.HasGlobalActor =
3369-
!Info.value().getGlobalActor().isNull();
33703367
Bits.AnyFunctionType.HasThrownError =
33713368
!Info.value().getThrownError().isNull();
3369+
assert(!Bits.AnyFunctionType.HasThrownError || Info->isThrowing());
33723370
Bits.AnyFunctionType.HasLifetimeDependenceInfo =
33733371
!Info.value().getLifetimeDependenceInfo().empty();
33743372
// The use of both assert() and static_assert() is intentional.
@@ -3381,7 +3379,6 @@ class AnyFunctionType : public TypeBase {
33813379
Bits.AnyFunctionType.HasExtInfo = false;
33823380
Bits.AnyFunctionType.HasClangTypeInfo = false;
33833381
Bits.AnyFunctionType.ExtInfoBits = 0;
3384-
Bits.AnyFunctionType.HasGlobalActor = false;
33853382
Bits.AnyFunctionType.HasThrownError = false;
33863383
Bits.AnyFunctionType.HasLifetimeDependenceInfo = false;
33873384
}
@@ -3423,7 +3420,7 @@ class AnyFunctionType : public TypeBase {
34233420
}
34243421

34253422
bool hasGlobalActor() const {
3426-
return Bits.AnyFunctionType.HasGlobalActor;
3423+
return ExtInfoBuilder::hasGlobalActorFromBits(Bits.AnyFunctionType.ExtInfoBits);
34273424
}
34283425

34293426
bool hasThrownError() const {
@@ -3442,6 +3439,15 @@ class AnyFunctionType : public TypeBase {
34423439

34433440
LifetimeDependenceInfo getLifetimeDependenceInfo() const;
34443441

3442+
FunctionTypeIsolation getIsolation() const {
3443+
if (hasExtInfo())
3444+
return getExtInfo().getIsolation();
3445+
return FunctionTypeIsolation::forNonIsolated();
3446+
}
3447+
bool isDynamicallyIsolated() const {
3448+
return getIsolation().isDynamic();
3449+
}
3450+
34453451
/// Retrieve the "effective" thrown interface type, or llvm::None if
34463452
/// this function cannot throw.
34473453
///
@@ -3693,6 +3699,15 @@ END_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
36933699
inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const {
36943700
return CanYield(getType()->getCanonicalType(), getFlags());
36953701
}
3702+
3703+
/// A convenience function to find out if any of the given parameters is
3704+
/// isolated.
3705+
///
3706+
/// You generally shouldn't need to call this when you're starting from a
3707+
/// function type; you can just check if the isolation on the type is
3708+
/// parameter isolation.
3709+
bool hasIsolatedParameter(ArrayRef<AnyFunctionType::Param> params);
3710+
36963711
/// FunctionType - A monomorphic function type, specified with an arrow.
36973712
///
36983713
/// For example:

include/swift/Demangling/TypeDecoder.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@ class TypeDecoder {
812812
Node->getNumChildren());
813813

814814
FunctionTypeFlags flags;
815+
ExtendedFunctionTypeFlags extFlags;
815816
if (Node->getKind() == NodeKind::ObjCBlock ||
816817
Node->getKind() == NodeKind::EscapingObjCBlock) {
817818
flags = flags.withConvention(FunctionMetadataConvention::Block);
@@ -847,6 +848,8 @@ class TypeDecoder {
847848
++firstChildIdx;
848849
}
849850

851+
// FIXME: other kinds of isolation
852+
850853
FunctionMetadataDifferentiabilityKind diffKind;
851854
if (Node->getChild(firstChildIdx)->getKind() ==
852855
NodeKind::DifferentiableFunctionType) {
@@ -895,6 +898,8 @@ class TypeDecoder {
895898

896899
thrownErrorType = thrownErrorResult.getType();
897900
++firstChildIdx;
901+
902+
extFlags = extFlags.withTypedThrows(true);
898903
}
899904

900905
bool isSendable = false;
@@ -941,8 +946,11 @@ class TypeDecoder {
941946
if (result.isError())
942947
return result;
943948

949+
if (extFlags != ExtendedFunctionTypeFlags())
950+
flags = flags.withExtendedFlags(true);
951+
944952
return Builder.createFunctionType(
945-
parameters, result.getType(), flags, diffKind, globalActorType,
953+
parameters, result.getType(), flags, extFlags, diffKind, globalActorType,
946954
thrownErrorType);
947955
}
948956
case NodeKind::ImplFunctionType: {

0 commit comments

Comments
 (0)