Skip to content

Commit 1a07030

Browse files
authored
Merge pull request #77028 from gottesmm/swift_task_runOnMainActor
[concurrency] Implement swift_task_runOnMainActor/hop to main actor thunk
2 parents 9850a28 + 0e0665b commit 1a07030

40 files changed

+1114
-170
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/AST/Decl.h"
1717
#include "swift/AST/FreestandingMacroExpansion.h"
18+
#include "swift/AST/SILThunkKind.h"
1819
#include "swift/AST/Types.h"
1920
#include "swift/Basic/Mangler.h"
2021
#include "swift/Basic/TaggedUnion.h"
@@ -314,6 +315,9 @@ class ASTMangler : public Mangler {
314315
DifferentiabilityKind kind,
315316
const AutoDiffConfig &config);
316317

318+
std::string mangleSILThunkKind(StringRef originalName,
319+
SILThunkKind thunkKind);
320+
317321
/// Mangle the AutoDiff generated declaration for the given:
318322
/// - Generated declaration kind: linear map struct or branching trace enum.
319323
/// - Mangled original function name.

include/swift/AST/SILThunkKind.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//===--- SILThunkKind.h ---------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
///
13+
/// \file This file contains a kind that defines the types of thunks that can be
14+
/// generated using a thunk inst. It provides an AST level interface that lets
15+
/// one generate the derived function kind and is also used to make adding such
16+
/// kinds to the mangler trivial.
17+
///
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef SWIFT_AST_SILTHUNKKIND_H
21+
#define SWIFT_AST_SILTHUNKKIND_H
22+
23+
#include "swift/AST/Types.h"
24+
25+
namespace swift {
26+
27+
class SILType;
28+
29+
struct SILThunkKind {
30+
enum InnerTy {
31+
Invalid = 0,
32+
33+
/// A thunk that just calls the passed in function. Used for testing
34+
/// purposes of the underlying thunking machinery.
35+
Identity = 1,
36+
37+
/// A thunk that checks if a value is on the main actor and if it isn't
38+
/// jumps to the main actor. It expects that the passed in function does not
39+
/// have any arguments, results, is synchronous, and does not throw.
40+
HopToMainActorIfNeeded = 2,
41+
42+
MaxValue = HopToMainActorIfNeeded,
43+
};
44+
45+
InnerTy innerTy;
46+
47+
SILThunkKind() : innerTy(InnerTy::Invalid) {}
48+
SILThunkKind(InnerTy innerTy) : innerTy(innerTy) {}
49+
SILThunkKind(unsigned inputInnerTy) : innerTy(InnerTy(inputInnerTy)) {
50+
assert(inputInnerTy <= MaxValue && "Invalid value");
51+
}
52+
53+
operator InnerTy() const { return innerTy; }
54+
55+
/// Given the current enum state returned the derived output function from
56+
/// \p inputFunction.
57+
///
58+
/// Defined in Instructions.cpp
59+
CanSILFunctionType getDerivedFunctionType(SILFunction *fn,
60+
CanSILFunctionType inputFunction,
61+
SubstitutionMap subMap) const;
62+
63+
/// Given the current enum state returned the derived output function from
64+
/// \p inputFunction.
65+
///
66+
/// Defined in Instructions.cpp
67+
SILType getDerivedFunctionType(SILFunction *fn, SILType inputFunctionType,
68+
SubstitutionMap subMap) const;
69+
70+
Demangle::MangledSILThunkKind getMangledKind() const {
71+
switch (innerTy) {
72+
case Invalid:
73+
return Demangle::MangledSILThunkKind::Invalid;
74+
case Identity:
75+
return Demangle::MangledSILThunkKind::Identity;
76+
case HopToMainActorIfNeeded:
77+
return Demangle::MangledSILThunkKind::HopToMainActorIfNeeded;
78+
}
79+
}
80+
};
81+
82+
} // namespace swift
83+
84+
#endif

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,9 @@ EXPERIMENTAL_FEATURE(CoroutineAccessorsUnwindOnCallerError, false)
433433
/// modify/read coroutines use the callee-allocated ABI
434434
EXPERIMENTAL_FEATURE(CoroutineAccessorsAllocateInCallee, false)
435435

436+
// When a parameter has unspecified isolation, infer it as main actor isolated.
437+
EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
438+
436439
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
437440
#undef EXPERIMENTAL_FEATURE
438441
#undef UPCOMING_FEATURE

include/swift/Demangling/Demangle.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ enum class MangledDifferentiabilityKind : char {
136136
Linear = 'l',
137137
};
138138

139+
enum class MangledSILThunkKind : char {
140+
Invalid = 0,
141+
Identity = 'I',
142+
HopToMainActorIfNeeded = 'H',
143+
};
144+
139145
/// The pass that caused the specialization to occur. We use this to make sure
140146
/// that two passes that generate similar changes do not yield the same
141147
/// mangling. This currently cannot happen, so this is just a safety measure

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ NODE(ReflectionMetadataAssocTypeDescriptor)
291291
NODE(ReflectionMetadataSuperclassDescriptor)
292292
NODE(GenericTypeParamDecl)
293293
NODE(CurryThunk)
294+
NODE(SILThunkIdentity)
295+
NODE(SILThunkHopToMainActorIfNeeded)
294296
NODE(DispatchThunk)
295297
NODE(MethodDescriptor)
296298
NODE(ProtocolRequirementsBaseDescriptor)

include/swift/Runtime/Concurrency.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,45 @@ TaskExecutorRef swift_task_getPreferredTaskExecutor(void);
963963
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
964964
bool swift_task_isCurrentExecutor(SerialExecutorRef executor);
965965

966+
/// This is an options enum that is used to pass flags to
967+
/// swift_task_isCurrentExecutorWithFlags. It is meant to be a flexible toggle.
968+
///
969+
/// Since this is an options enum, so all values should be powers of 2.
970+
///
971+
/// NOTE: We are purposely leaving this as a uint64_t so that on all platforms
972+
/// this could be a pointer to a different enum instance if we need it to be.
973+
enum swift_task_is_current_executor_flag : uint64_t {
974+
/// We aren't passing any flags.
975+
None = 0x0,
976+
977+
/// This is not used today, but is just future ABI reservation.
978+
///
979+
/// The intention is that we may want the ability to tell future versions of
980+
/// the runtime that this uint64_t is actually a pointer that it should
981+
/// dereference and then have further extended behavior controlled by a
982+
/// different enum. By placing this here, we ensure that we will have a tagged
983+
/// pointer compatible flag for this purpose.
984+
TaggedPointer = 0x1,
985+
986+
/// This is not used today, but is just future ABI reservation.
987+
///
988+
/// \see swift_task_is_current_executor_flag::TaggedPointer
989+
TaggedPointer2 = 0x2,
990+
991+
/// This is not used today, but is just future ABI reservation.
992+
///
993+
/// \see swift_task_is_current_executor_flag::TaggedPointer
994+
TaggedPointer3 = 0x4,
995+
996+
/// The routine should assert on failure.
997+
Assert = 0x8,
998+
};
999+
1000+
SWIFT_EXPORT_FROM(swift_Concurrency)
1001+
SWIFT_CC(swift)
1002+
bool swift_task_isCurrentExecutorWithFlags(
1003+
SerialExecutorRef executor, swift_task_is_current_executor_flag flags);
1004+
9661005
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
9671006
void swift_task_reportUnexpectedExecutor(
9681007
const unsigned char *file, uintptr_t fileLength, bool fileIsASCII,

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,13 @@ class SILBuilder {
12511251
return createThunk(Loc, Op, ThunkInst::Kind::Identity, substitutionMap);
12521252
}
12531253

1254+
ThunkInst *
1255+
createHopToMainActorIfNeededThunk(SILLocation Loc, SILValue Op,
1256+
SubstitutionMap substitutionMap = {}) {
1257+
return createThunk(Loc, Op, ThunkInst::Kind::HopToMainActorIfNeeded,
1258+
substitutionMap);
1259+
}
1260+
12541261
ConvertEscapeToNoEscapeInst *
12551262
createConvertEscapeToNoEscape(SILLocation Loc, SILValue Op, SILType Ty,
12561263
bool lifetimeGuaranteed) {

include/swift/SIL/SILInstruction.h

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Decl.h"
2424
#include "swift/AST/GenericSignature.h"
2525
#include "swift/AST/ProtocolConformanceRef.h"
26+
#include "swift/AST/SILThunkKind.h"
2627
#include "swift/AST/SubstitutionMap.h"
2728
#include "swift/AST/TypeAlignments.h"
2829
#include "swift/Basic/Compiler.h"
@@ -5887,41 +5888,7 @@ class ThunkInst final
58875888
: public UnaryInstructionWithTypeDependentOperandsBase<
58885889
SILInstructionKind::ThunkInst, ThunkInst, SingleValueInstruction> {
58895890
public:
5890-
struct Kind {
5891-
enum InnerTy {
5892-
Invalid = 0,
5893-
5894-
/// A thunk that just calls the passed in function. Used for testing
5895-
/// purposes of the underlying thunking machinery.
5896-
Identity = 1,
5897-
5898-
MaxValue = Identity,
5899-
};
5900-
5901-
InnerTy innerTy;
5902-
5903-
Kind() : innerTy(InnerTy::Invalid) {}
5904-
Kind(InnerTy innerTy) : innerTy(innerTy) {}
5905-
Kind(unsigned inputInnerTy) : innerTy(InnerTy(inputInnerTy)) {
5906-
assert(inputInnerTy <= MaxValue && "Invalid value");
5907-
}
5908-
5909-
operator InnerTy() const { return innerTy; }
5910-
5911-
/// Given the current enum state returned the derived output function from
5912-
/// \p inputFunction.
5913-
CanSILFunctionType getDerivedFunctionType(SILFunction *fn,
5914-
CanSILFunctionType inputFunction,
5915-
SubstitutionMap subMap) const;
5916-
5917-
SILType getDerivedFunctionType(SILFunction *fn, SILType inputFunctionType,
5918-
SubstitutionMap subMap) const {
5919-
auto fType = inputFunctionType.castTo<SILFunctionType>();
5920-
return SILType::getPrimitiveType(
5921-
getDerivedFunctionType(fn, fType, subMap),
5922-
inputFunctionType.getCategory());
5923-
}
5924-
};
5891+
using Kind = SILThunkKind;
59255892

59265893
/// The type of thunk we are supposed to produce.
59275894
Kind kind;

lib/AST/ASTMangler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,16 @@ std::string ASTMangler::mangleSILDifferentiabilityWitness(StringRef originalName
636636
return finalize();
637637
}
638638

639+
std::string ASTMangler::mangleSILThunkKind(StringRef originalName,
640+
SILThunkKind thunkKind) {
641+
beginManglingWithoutPrefix();
642+
appendOperator(originalName);
643+
// Prefix for thunk inst based thunks
644+
auto code = (char)thunkKind.getMangledKind();
645+
appendOperator("TT", StringRef(&code, 1));
646+
return finalize();
647+
}
648+
639649
std::string ASTMangler::mangleAutoDiffGeneratedDeclaration(
640650
AutoDiffGeneratedDeclarationKind declKind, StringRef origFnName,
641651
unsigned bbId, AutoDiffLinearMapKind linearMapKind,

lib/AST/FeatureSet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ UNINTERESTING_FEATURE(SameElementRequirements)
199199
UNINTERESTING_FEATURE(UnspecifiedMeansMainActorIsolated)
200200
UNINTERESTING_FEATURE(GlobalActorInferenceCutoff)
201201
UNINTERESTING_FEATURE(KeyPathWithStaticMembers)
202+
UNINTERESTING_FEATURE(GenerateForceToMainActorThunks)
202203

203204
static bool usesFeatureSendingArgsAndResults(Decl *decl) {
204205
auto isFunctionTypeWithSending = [](Type type) {

0 commit comments

Comments
 (0)