Skip to content

Commit 30d91d3

Browse files
Merge pull request #79625 from nate-chandler/general-coro/20250212/1
[CoroutineAccessors] Use retcon.once variant.
2 parents 4a119a4 + dd8cbe3 commit 30d91d3

37 files changed

+1318
-226
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ types where the metadata itself has unknown layout.)
235235
global ::= global 'TF' // distributed method accessor
236236
global ::= global 'TI' // implementation of a dynamic_replaceable function
237237
global ::= global 'Tu' // async function pointer of a function
238+
global ::= global 'Tv' // coro function pointer of a function
238239
global ::= global 'TX' // function pointer of a dynamic_replaceable function
239240
global ::= global 'Twb' // back deployment thunk
240241
global ::= global 'TwB' // back deployment fallback function

include/swift/ABI/Coro.h

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===---------- Coro.h - ABI structures for coroutines ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
// Swift ABI describing the coroutine ABI.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_ABI_CORO_H
18+
#define SWIFT_ABI_CORO_H
19+
20+
#include "swift/Basic/FlagSet.h"
21+
#include <cstddef>
22+
#include <cstdint>
23+
24+
namespace swift {
25+
26+
enum class CoroAllocatorKind : uint8_t {
27+
// stacksave/stackrestore
28+
Sync = 0,
29+
// swift_task_alloc/swift_task_dealloc_through
30+
Async = 1,
31+
// malloc/free
32+
Malloc = 2,
33+
};
34+
35+
class CoroAllocatorFlags : public FlagSet<uint32_t> {
36+
public:
37+
// clang-format off
38+
enum {
39+
Kind = 0,
40+
Kind_width = 8,
41+
42+
// 24 reserved bits
43+
};
44+
// clang-format on
45+
46+
constexpr explicit CoroAllocatorFlags(uint32_t bits) : FlagSet(bits) {}
47+
CoroAllocatorFlags(CoroAllocatorKind kind) { setKind(kind); }
48+
constexpr CoroAllocatorFlags() {}
49+
50+
FLAGSET_DEFINE_FIELD_ACCESSORS(Kind, Kind_width, CoroAllocatorKind, getKind,
51+
setKind)
52+
};
53+
54+
using CoroAllocation = void *;
55+
using CoroAllocateFn = CoroAllocation (*)(size_t);
56+
using CoroDealllocateFn = void (*)(CoroAllocation);
57+
58+
struct CoroAllocator {
59+
CoroAllocatorFlags flags;
60+
CoroAllocateFn allocate;
61+
CoroDealllocateFn deallocate;
62+
63+
/// Whether the allocator should deallocate memory on calls to
64+
/// swift_coro_dealloc.
65+
constexpr bool shouldDeallocateImmediately() {
66+
// Only the "mallocator" should immediately deallocate in
67+
// swift_coro_dealloc. It must because the ABI does not provide a means for
68+
// the callee to return its allocations to the caller.
69+
//
70+
// Async allocations can be deferred until the first non-coroutine caller
71+
// from where swift_task_dealloc_through can be called and passed the
72+
// caller-allocated fixed-per-callee-sized-frame.
73+
// Stack allocations just pop the stack.
74+
return flags.getKind() == CoroAllocatorKind::Malloc;
75+
}
76+
};
77+
78+
} // end namespace swift
79+
80+
#endif

include/swift/AST/IRGenOptions.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class IRGenOptions {
386386
unsigned LazyInitializeClassMetadata : 1;
387387
unsigned LazyInitializeProtocolConformances : 1;
388388
unsigned IndirectAsyncFunctionPointer : 1;
389+
unsigned IndirectCoroFunctionPointer : 1;
389390

390391
/// Use absolute function references instead of relative ones.
391392
/// Mainly used on WebAssembly, that doesn't support relative references
@@ -580,10 +581,10 @@ class IRGenOptions {
580581
HasValueNamesSetting(false), ValueNames(false),
581582
ReflectionMetadata(ReflectionMetadataMode::Runtime),
582583
EnableReflectionNames(true), DisableLLVMMergeFunctions(false),
583-
EnableAnonymousContextMangledNames(false),
584-
ForcePublicLinkage(false), LazyInitializeClassMetadata(false),
584+
EnableAnonymousContextMangledNames(false), ForcePublicLinkage(false),
585+
LazyInitializeClassMetadata(false),
585586
LazyInitializeProtocolConformances(false),
586-
IndirectAsyncFunctionPointer(false),
587+
IndirectAsyncFunctionPointer(false), IndirectCoroFunctionPointer(false),
587588
CompactAbsoluteFunctionPointer(false), DisableLegacyTypeInfo(false),
588589
PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true),
589590
UseTypeLayoutValueHandling(true), ForceStructTypeLayouts(false),
@@ -598,16 +599,15 @@ class IRGenOptions {
598599
EnableGlobalISel(false), VirtualFunctionElimination(false),
599600
WitnessMethodElimination(false), ConditionalRuntimeRecords(false),
600601
InternalizeAtLink(false), InternalizeSymbols(false),
601-
MergeableSymbols(false),
602-
EmitGenericRODatas(true), NoPreallocatedInstantiationCaches(false),
602+
MergeableSymbols(false), EmitGenericRODatas(true),
603+
NoPreallocatedInstantiationCaches(false),
603604
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
604605
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
605606
UseFragileResilientProtocolWitnesses(false), EnableHotColdSplit(false),
606607
EmitAsyncFramePushPopMetadata(true), EmitTypeMallocForCoroFrame(false),
607608
EmitYieldOnce2AsYieldOnce(true), AsyncFramePointerAll(false),
608-
UseProfilingMarkerThunks(false),
609-
DebugInfoForProfiling(false), CmdArgs(),
610-
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
609+
UseProfilingMarkerThunks(false), DebugInfoForProfiling(false),
610+
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
611611
TypeInfoFilter(TypeInfoDumpFilter::All),
612612
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),
613613
CASObjMode(llvm::CASBackendMode::Native) {

include/swift/IRGen/Linking.h

Lines changed: 142 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,11 @@ class LinkEntity {
389389
/// The pointer is an AbstractFunctionDecl*.
390390
AsyncFunctionPointerAST,
391391

392+
/// The same as CoroFunctionPointer but with a different stored value, for
393+
/// use by TBDGen.
394+
/// The pointer is an AbstractFunctionDecl*.
395+
CoroFunctionPointerAST,
396+
392397
/// The pointer is a SILFunction*.
393398
DynamicallyReplaceableFunctionKey,
394399

@@ -551,6 +556,39 @@ class LinkEntity {
551556
/// Pointer is the (generalized) existential type.
552557
/// SecondaryPointer is the GenericSignatureImpl*.
553558
ExtendedExistentialTypeShape,
559+
560+
/// A global struct containing a relative pointer to the single-yield
561+
/// coroutine ramp function and the fixed-size to be allocated in the
562+
/// caller.
563+
/// The pointer is a SILFunction*.
564+
CoroFunctionPointer,
565+
566+
/// An coro function pointer for a method dispatch thunk. The pointer is
567+
/// a FuncDecl* inside a protocol or a class.
568+
DispatchThunkCoroFunctionPointer,
569+
570+
/// An coro function pointer for a method dispatch thunk for an
571+
/// initializing constructor. The pointer is a ConstructorDecl* inside a
572+
/// class.
573+
DispatchThunkInitializerCoroFunctionPointer,
574+
575+
/// An coro function pointer for a method dispatch thunk for an allocating
576+
/// constructor. The pointer is a ConstructorDecl* inside a protocol or
577+
/// a class.
578+
DispatchThunkAllocatorCoroFunctionPointer,
579+
580+
/// An coro function pointer for a distributed thunk.
581+
/// The pointer is a FuncDecl* inside an actor (class).
582+
DistributedThunkCoroFunctionPointer,
583+
584+
/// An coro function pointer to a partial apply forwarder.
585+
/// The pointer is the llvm::Function* for a partial apply forwarder.
586+
PartialApplyForwarderCoroFunctionPointer,
587+
588+
/// An coro function pointer for a distributed accessor (method or
589+
/// property).
590+
/// The pointer is a SILFunction*.
591+
DistributedAccessorCoroFunctionPointer,
554592
};
555593
friend struct llvm::DenseMapInfo<LinkEntity>;
556594

@@ -572,9 +610,7 @@ class LinkEntity {
572610
return !(LHS == RHS);
573611
}
574612

575-
static bool isDeclKind(Kind k) {
576-
return k <= Kind::AsyncFunctionPointerAST;
577-
}
613+
static bool isDeclKind(Kind k) { return k <= Kind::CoroFunctionPointerAST; }
578614
static bool isTypeKind(Kind k) {
579615
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
580616
}
@@ -1457,6 +1493,109 @@ class LinkEntity {
14571493
return entity;
14581494
}
14591495

1496+
static LinkEntity forCoroFunctionPointer(LinkEntity other) {
1497+
LinkEntity entity;
1498+
entity.Pointer = other.Pointer;
1499+
entity.SecondaryPointer = nullptr;
1500+
1501+
switch (other.getKind()) {
1502+
case LinkEntity::Kind::SILFunction:
1503+
entity.Data = LINKENTITY_SET_FIELD(
1504+
Kind, unsigned(LinkEntity::Kind::CoroFunctionPointer));
1505+
break;
1506+
1507+
case LinkEntity::Kind::DispatchThunk:
1508+
entity.Data = LINKENTITY_SET_FIELD(
1509+
Kind, unsigned(LinkEntity::Kind::DispatchThunkCoroFunctionPointer));
1510+
break;
1511+
1512+
case LinkEntity::Kind::DispatchThunkInitializer:
1513+
entity.Data = LINKENTITY_SET_FIELD(
1514+
Kind,
1515+
unsigned(
1516+
LinkEntity::Kind::DispatchThunkInitializerCoroFunctionPointer));
1517+
break;
1518+
1519+
case LinkEntity::Kind::DispatchThunkAllocator:
1520+
entity.Data = LINKENTITY_SET_FIELD(
1521+
Kind,
1522+
unsigned(
1523+
LinkEntity::Kind::DispatchThunkAllocatorCoroFunctionPointer));
1524+
break;
1525+
case LinkEntity::Kind::PartialApplyForwarder:
1526+
entity.Data = LINKENTITY_SET_FIELD(
1527+
Kind,
1528+
unsigned(LinkEntity::Kind::PartialApplyForwarderCoroFunctionPointer));
1529+
break;
1530+
1531+
case LinkEntity::Kind::DistributedAccessor: {
1532+
entity.Data = LINKENTITY_SET_FIELD(
1533+
Kind,
1534+
unsigned(LinkEntity::Kind::DistributedAccessorCoroFunctionPointer));
1535+
break;
1536+
}
1537+
1538+
default:
1539+
llvm_unreachable("Link entity kind cannot have an coro function pointer");
1540+
}
1541+
1542+
return entity;
1543+
}
1544+
1545+
static LinkEntity forCoroFunctionPointer(SILDeclRef declRef) {
1546+
LinkEntity entity;
1547+
entity.setForDecl(declRef.isDistributedThunk()
1548+
? Kind::DistributedThunkCoroFunctionPointer
1549+
: Kind::CoroFunctionPointerAST,
1550+
declRef.getAbstractFunctionDecl());
1551+
entity.SecondaryPointer =
1552+
reinterpret_cast<void *>(static_cast<uintptr_t>(declRef.kind));
1553+
return entity;
1554+
}
1555+
1556+
LinkEntity getUnderlyingEntityForCoroFunctionPointer() const {
1557+
LinkEntity entity;
1558+
entity.Pointer = Pointer;
1559+
entity.SecondaryPointer = nullptr;
1560+
1561+
switch (getKind()) {
1562+
case LinkEntity::Kind::CoroFunctionPointer:
1563+
entity.Data =
1564+
LINKENTITY_SET_FIELD(Kind, unsigned(LinkEntity::Kind::SILFunction));
1565+
break;
1566+
1567+
case LinkEntity::Kind::DispatchThunkCoroFunctionPointer:
1568+
entity.Data =
1569+
LINKENTITY_SET_FIELD(Kind, unsigned(LinkEntity::Kind::DispatchThunk));
1570+
break;
1571+
1572+
case LinkEntity::Kind::DispatchThunkInitializerCoroFunctionPointer:
1573+
entity.Data = LINKENTITY_SET_FIELD(
1574+
Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializer));
1575+
break;
1576+
1577+
case LinkEntity::Kind::DispatchThunkAllocatorCoroFunctionPointer:
1578+
entity.Data = LINKENTITY_SET_FIELD(
1579+
Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocator));
1580+
break;
1581+
1582+
case LinkEntity::Kind::PartialApplyForwarderCoroFunctionPointer:
1583+
entity.Data = LINKENTITY_SET_FIELD(
1584+
Kind, unsigned(LinkEntity::Kind::PartialApplyForwarder));
1585+
break;
1586+
1587+
case LinkEntity::Kind::DistributedAccessorCoroFunctionPointer:
1588+
entity.Data = LINKENTITY_SET_FIELD(
1589+
Kind, unsigned(LinkEntity::Kind::DistributedAccessor));
1590+
break;
1591+
1592+
default:
1593+
llvm_unreachable("Link entity is not an coro function pointer");
1594+
}
1595+
1596+
return entity;
1597+
}
1598+
14601599
void mangle(ASTContext &Ctx, llvm::raw_ostream &out) const;
14611600
void mangle(ASTContext &Ctx, SmallVectorImpl<char> &buffer) const;
14621601
std::string mangleAsString(ASTContext &Ctx) const;

include/swift/Runtime/Concurrency.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_RUNTIME_CONCURRENCY_H
1919

2020
#include "swift/ABI/AsyncLet.h"
21+
#include "swift/ABI/Coro.h"
2122
#include "swift/ABI/Task.h"
2223
#include "swift/ABI/TaskGroup.h"
2324

@@ -119,6 +120,35 @@ void *swift_task_alloc(size_t size);
119120
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
120121
void swift_task_dealloc(void *ptr);
121122

123+
/// Deallocate multiple memory allocations in a task.
124+
///
125+
/// The pointer provided must be a pointer previously allocated on
126+
/// this task that has not yet been deallocated. All allocations up to and
127+
/// including that allocation will be deallocated.
128+
SWIFT_EXPORT_FROM(swift_Concurrency)
129+
SWIFT_CC(swift) void swift_task_dealloc_through(void *ptr);
130+
131+
// TODO: CoroutineAccessors: Eliminate this entry point and replace its uses
132+
// with direct references the globals.
133+
SWIFT_EXPORT_FROM(swift_Concurrency)
134+
SWIFT_CC(swift)
135+
CoroAllocator *swift_coro_getGlobalAllocator(CoroAllocatorFlags flags);
136+
137+
// TODO: CoroutineAccessors: Mark the underlying struct const.
138+
SWIFT_EXPORT_FROM(swift_Concurrency)
139+
CoroAllocator *const _swift_coro_task_allocator;
140+
141+
// TODO: CoroutineAccessors: Move these declarations back to swiftCore {{
142+
SWIFT_EXPORT_FROM(swift_Concurrency)
143+
SWIFT_CC(swift) void *swift_coro_alloc(CoroAllocator *allocator, size_t size);
144+
SWIFT_EXPORT_FROM(swift_Concurrency)
145+
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
146+
147+
// TODO: CoroutineAccessors: Mark the underlying struct const.
148+
SWIFT_EXPORT_FROM(swift_Concurrency)
149+
CoroAllocator *const _swift_coro_malloc_allocator;
150+
// }} TODO: CoroutineAccessors
151+
122152
/// Cancel a task and all of its child tasks.
123153
///
124154
/// This can be called from any thread.

include/swift/Runtime/Coro.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===-------- Coro.h - Runtime interface for coroutines ---------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 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+
// The runtime interface for coroutines.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_RUNTIME_CORO_H
18+
#define SWIFT_RUNTIME_CORO_H
19+
20+
#include "swift/ABI/Coro.h"
21+
#include "swift/Runtime/Config.h"
22+
#include <cstddef>
23+
24+
namespace swift {} // end namespace swift
25+
26+
#endif

0 commit comments

Comments
 (0)