mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CoroutineAccessors] Directly reference allocators
Replace the call to a runtime function that looks up the allocator with a direct reference to a just-emittedd sought-after global allocator.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#ifndef SWIFT_IRGEN_LINKING_H
|
||||
#define SWIFT_IRGEN_LINKING_H
|
||||
|
||||
#include "swift/ABI/Coro.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ProtocolAssociations.h"
|
||||
@@ -24,8 +25,8 @@
|
||||
#include "swift/SIL/SILGlobalVariable.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/GlobalObject.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
namespace llvm {
|
||||
@@ -165,6 +166,9 @@ class LinkEntity {
|
||||
ExtendedExistentialIsUniqueMask = 0x100,
|
||||
ExtendedExistentialIsSharedShift = 9,
|
||||
ExtendedExistentialIsSharedMask = 0x200,
|
||||
|
||||
// Used by CoroAllocator. 2 bits.
|
||||
CoroAllocatorKindShift = 8, CoroAllocatorKindMask = 0x300,
|
||||
};
|
||||
#define LINKENTITY_SET_FIELD(field, value) (value << field##Shift)
|
||||
#define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift)
|
||||
@@ -594,6 +598,9 @@ class LinkEntity {
|
||||
/// property).
|
||||
/// The pointer is a SILFunction*.
|
||||
DistributedAccessorCoroFunctionPointer,
|
||||
|
||||
/// An allocator to be passed to swift_coro_alloc and swift_coro_dealloc.
|
||||
CoroAllocator,
|
||||
};
|
||||
friend struct llvm::DenseMapInfo<LinkEntity>;
|
||||
|
||||
@@ -1498,6 +1505,15 @@ public:
|
||||
return entity;
|
||||
}
|
||||
|
||||
static LinkEntity forCoroAllocator(CoroAllocatorKind kind) {
|
||||
LinkEntity entity;
|
||||
entity.Pointer = nullptr;
|
||||
entity.SecondaryPointer = nullptr;
|
||||
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::CoroAllocator)) |
|
||||
LINKENTITY_SET_FIELD(CoroAllocatorKind, unsigned(kind));
|
||||
return entity;
|
||||
}
|
||||
|
||||
static LinkEntity forCoroFunctionPointer(LinkEntity other) {
|
||||
LinkEntity entity;
|
||||
entity.Pointer = other.Pointer;
|
||||
@@ -1709,6 +1725,11 @@ public:
|
||||
SecondaryPointer);
|
||||
}
|
||||
|
||||
CoroAllocatorKind getCoroAllocatorKind() const {
|
||||
assert(getKind() == Kind::CoroAllocator);
|
||||
return CoroAllocatorKind(LINKENTITY_GET_FIELD(Data, CoroAllocatorKind));
|
||||
}
|
||||
|
||||
CanGenericSignature getExtendedExistentialTypeShapeGenSig() const {
|
||||
assert(getKind() == Kind::ExtendedExistentialTypeShape);
|
||||
return CanGenericSignature(
|
||||
|
||||
@@ -128,25 +128,11 @@ void swift_task_dealloc(void *ptr);
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
SWIFT_CC(swift) void swift_task_dealloc_through(void *ptr);
|
||||
|
||||
// TODO: CoroutineAccessors: Eliminate this entry point and replace its uses
|
||||
// with direct references the globals.
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
SWIFT_CC(swift)
|
||||
CoroAllocator *swift_coro_getGlobalAllocator(CoroAllocatorFlags flags);
|
||||
|
||||
// TODO: CoroutineAccessors: Mark the underlying struct const.
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
CoroAllocator *const _swift_coro_task_allocator;
|
||||
|
||||
// TODO: CoroutineAccessors: Move these declarations back to swiftCore {{
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
SWIFT_CC(swift) void *swift_coro_alloc(CoroAllocator *allocator, size_t size);
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
|
||||
|
||||
// TODO: CoroutineAccessors: Mark the underlying struct const.
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency)
|
||||
CoroAllocator *const _swift_coro_malloc_allocator;
|
||||
// }} TODO: CoroutineAccessors
|
||||
|
||||
/// Cancel a task and all of its child tasks.
|
||||
|
||||
@@ -3028,16 +3028,6 @@ FUNCTION(CoroDealloc,
|
||||
EFFECT(RuntimeEffect::Deallocating, RuntimeEffect::Concurrency),
|
||||
UNKNOWN_MEMEFFECTS)
|
||||
|
||||
// const CoroAllocator *swift_coro_getGlobalAllocator(CoroAllocatorFlags flags);
|
||||
FUNCTION(CoroGetGlobalAllocator,
|
||||
_Concurrency, swift_coro_getGlobalAllocator, SwiftCC,
|
||||
CoroutineAccessorsAvailability,
|
||||
RETURNS(CoroAllocatorPtrTy),
|
||||
ARGS(CoroAllocatorFlagsTy),
|
||||
ATTRS(NoUnwind, WillReturn),
|
||||
EFFECT(RuntimeEffect::Allocating),
|
||||
UNKNOWN_MEMEFFECTS)
|
||||
|
||||
#undef RETURNS
|
||||
#undef ARGS
|
||||
#undef ATTRS
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <optional>
|
||||
|
||||
#include "CallEmission.h"
|
||||
#include "ConstantBuilder.h"
|
||||
#include "EntryPointArgumentEmission.h"
|
||||
#include "Explosion.h"
|
||||
#include "GenCall.h"
|
||||
@@ -57,8 +58,8 @@
|
||||
#include "GenType.h"
|
||||
#include "IRGenDebugInfo.h"
|
||||
#include "IRGenFunction.h"
|
||||
#include "IRGenModule.h"
|
||||
#include "IRGenMangler.h"
|
||||
#include "IRGenModule.h"
|
||||
#include "LoadableTypeInfo.h"
|
||||
#include "NativeConventionSchema.h"
|
||||
#include "Signature.h"
|
||||
@@ -5197,18 +5198,47 @@ Address irgen::emitAllocYieldManyCoroutineBuffer(IRGenFunction &IGF) {
|
||||
return createOpaqueBufferAlloca(IGF, getYieldManyCoroutineBufferSize(IGF.IGM),
|
||||
getYieldManyCoroutineBufferAlignment(IGF.IGM));
|
||||
}
|
||||
|
||||
static llvm::Constant *getAddrOfGlobalCoroAllocator(IRGenModule &IGM,
|
||||
CoroAllocatorKind kind,
|
||||
llvm::Constant *allocFn,
|
||||
llvm::Constant *deallocFn) {
|
||||
auto entity = LinkEntity::forCoroAllocator(kind);
|
||||
auto taskAllocator = IGM.getOrCreateLazyGlobalVariable(
|
||||
entity,
|
||||
[&](ConstantInitBuilder &builder) -> ConstantInitFuture {
|
||||
auto allocator = builder.beginStruct(IGM.CoroAllocatorTy);
|
||||
allocator.addInt32(CoroAllocatorFlags(kind).getOpaqueValue());
|
||||
allocator.add(allocFn);
|
||||
allocator.add(deallocFn);
|
||||
return allocator.finishAndCreateFuture();
|
||||
},
|
||||
[&](llvm::GlobalVariable *var) { var->setConstant(true); });
|
||||
return taskAllocator;
|
||||
}
|
||||
llvm::Constant *IRGenModule::getAddrOfGlobalCoroMallocAllocator() {
|
||||
return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Malloc,
|
||||
getMallocFn(), getFreeFn());
|
||||
}
|
||||
llvm::Constant *IRGenModule::getAddrOfGlobalCoroAsyncTaskAllocator() {
|
||||
return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Async,
|
||||
getTaskAllocFn(), getTaskDeallocFn());
|
||||
}
|
||||
llvm::Value *
|
||||
irgen::emitYieldOnce2CoroutineAllocator(IRGenFunction &IGF,
|
||||
std::optional<CoroAllocatorKind> kind) {
|
||||
if (!kind) {
|
||||
return IGF.getCoroutineAllocator();
|
||||
}
|
||||
CoroAllocatorFlags flags(*kind);
|
||||
auto *flagsValue = llvm::ConstantInt::get(IGF.IGM.CoroAllocatorFlagsTy,
|
||||
flags.getOpaqueValue());
|
||||
|
||||
return IGF.Builder.CreateCall(
|
||||
IGF.IGM.getCoroGetGlobalAllocatorFunctionPointer(), {flagsValue});
|
||||
switch (*kind) {
|
||||
case CoroAllocatorKind::Stack:
|
||||
return llvm::ConstantPointerNull::get(IGF.IGM.CoroAllocatorPtrTy);
|
||||
case CoroAllocatorKind::Async:
|
||||
return IGF.IGM.getAddrOfGlobalCoroAsyncTaskAllocator();
|
||||
case CoroAllocatorKind::Malloc:
|
||||
return IGF.IGM.getAddrOfGlobalCoroMallocAllocator();
|
||||
}
|
||||
llvm_unreachable("unhandled case");
|
||||
}
|
||||
StackAddress irgen::emitAllocYieldOnce2CoroutineFrame(IRGenFunction &IGF,
|
||||
llvm::Value *size) {
|
||||
|
||||
@@ -832,8 +832,8 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
|
||||
CoroAllocatorTy = createStructType(*this, "swift.coro_allocator",
|
||||
{
|
||||
Int32Ty, // CoroAllocator.Flags
|
||||
CoroAllocateFnTy,
|
||||
CoroDeallocateFnTy,
|
||||
CoroAllocateFnTy->getPointerTo(),
|
||||
CoroDeallocateFnTy->getPointerTo(),
|
||||
});
|
||||
CoroAllocatorPtrTy = CoroAllocatorTy->getPointerTo();
|
||||
}
|
||||
|
||||
@@ -1671,6 +1671,9 @@ public:
|
||||
ConstantInit init);
|
||||
SILFunction *getSILFunctionForCoroFunctionPointer(llvm::Constant *cfp);
|
||||
|
||||
llvm::Constant *getAddrOfGlobalCoroMallocAllocator();
|
||||
llvm::Constant *getAddrOfGlobalCoroAsyncTaskAllocator();
|
||||
|
||||
llvm::Function *getAddrOfDispatchThunk(SILDeclRef declRef,
|
||||
ForDefinition_t forDefinition);
|
||||
void emitDispatchThunk(SILDeclRef declRef);
|
||||
|
||||
@@ -577,6 +577,16 @@ std::string LinkEntity::mangleAsString(ASTContext &Ctx) const {
|
||||
Result.append("Twc");
|
||||
return Result;
|
||||
}
|
||||
case Kind::CoroAllocator: {
|
||||
switch (getCoroAllocatorKind()) {
|
||||
case CoroAllocatorKind::Stack:
|
||||
llvm::report_fatal_error("attempting to mangle the coro stack allocator");
|
||||
case CoroAllocatorKind::Async:
|
||||
return "_swift_coro_async_allocator";
|
||||
case CoroAllocatorKind::Malloc:
|
||||
return "_swift_coro_malloc_allocator";
|
||||
}
|
||||
}
|
||||
}
|
||||
llvm_unreachable("bad entity kind!");
|
||||
}
|
||||
@@ -948,6 +958,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
|
||||
return getUnderlyingEntityForCoroFunctionPointer().getLinkage(
|
||||
forDefinition);
|
||||
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
|
||||
case Kind::CoroAllocator:
|
||||
return SILLinkage::Shared;
|
||||
}
|
||||
llvm_unreachable("bad link entity kind");
|
||||
}
|
||||
@@ -1051,6 +1063,7 @@ bool LinkEntity::isContextDescriptor() const {
|
||||
case Kind::CoroFunctionPointerAST:
|
||||
case Kind::DistributedThunkCoroFunctionPointer:
|
||||
case Kind::KnownCoroFunctionPointer:
|
||||
case Kind::CoroAllocator:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("invalid descriptor");
|
||||
@@ -1188,6 +1201,8 @@ llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const {
|
||||
case Kind::DistributedThunkCoroFunctionPointer:
|
||||
case Kind::KnownCoroFunctionPointer:
|
||||
return IGM.CoroFunctionPointerPtrTy;
|
||||
case Kind::CoroAllocator:
|
||||
return IGM.CoroAllocatorTy;
|
||||
default:
|
||||
llvm_unreachable("declaration LLVM type not specified");
|
||||
}
|
||||
@@ -1220,6 +1235,7 @@ Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
|
||||
case Kind::OpaqueTypeDescriptorRecord:
|
||||
case Kind::AccessibleFunctionRecord:
|
||||
case Kind::ExtendedExistentialTypeShape:
|
||||
case Kind::CoroAllocator:
|
||||
return Alignment(4);
|
||||
case Kind::AsyncFunctionPointer:
|
||||
case Kind::DispatchThunkAsyncFunctionPointer:
|
||||
@@ -1359,6 +1375,7 @@ bool LinkEntity::isText() const {
|
||||
case Kind::DynamicallyReplaceableFunctionVariable:
|
||||
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
|
||||
case Kind::ExtendedExistentialTypeShape:
|
||||
case Kind::CoroAllocator:
|
||||
return true;
|
||||
case Kind::ObjCClass:
|
||||
case Kind::ObjCClassRef:
|
||||
@@ -1520,6 +1537,7 @@ bool LinkEntity::isWeakImported(ModuleDecl *module) const {
|
||||
case Kind::DifferentiabilityWitness:
|
||||
case Kind::AccessibleFunctionRecord:
|
||||
case Kind::ExtendedExistentialTypeShape:
|
||||
case Kind::CoroAllocator:
|
||||
return false;
|
||||
|
||||
case Kind::AsyncFunctionPointer:
|
||||
@@ -1656,6 +1674,7 @@ DeclContext *LinkEntity::getDeclContextForEmission() const {
|
||||
case Kind::TypeMetadataDemanglingCacheVariable:
|
||||
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
|
||||
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
|
||||
case Kind::CoroAllocator:
|
||||
assert(isAlwaysSharedLinkage() && "kind should always be shared linkage");
|
||||
return nullptr;
|
||||
|
||||
@@ -1708,6 +1727,7 @@ bool LinkEntity::isAlwaysSharedLinkage() const {
|
||||
case Kind::TypeMetadataDemanglingCacheVariable:
|
||||
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
|
||||
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
|
||||
case Kind::CoroAllocator:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
||||
@@ -69,39 +69,10 @@ void swift::_swift_task_dealloc_specific(AsyncTask *task, void *ptr) {
|
||||
allocator(task).dealloc(ptr);
|
||||
}
|
||||
|
||||
static void *swift_task_alloc_thunk(size_t size) {
|
||||
return swift_task_alloc(size);
|
||||
}
|
||||
|
||||
static void swift_task_dealloc_thunk(void *ptr) { swift_task_dealloc(ptr); }
|
||||
|
||||
void swift::swift_task_dealloc_through(void *ptr) {
|
||||
allocator(swift_task_getCurrent()).deallocThrough(ptr);
|
||||
}
|
||||
|
||||
static CoroAllocator CoroTaskAllocatorImpl{
|
||||
CoroAllocatorFlags(/*CoroAllocatorKind::Async*/ 1), swift_task_alloc_thunk,
|
||||
swift_task_dealloc_thunk};
|
||||
|
||||
CoroAllocator *const swift::_swift_coro_task_allocator = &CoroTaskAllocatorImpl;
|
||||
|
||||
CoroAllocator *swift::swift_coro_getGlobalAllocator(CoroAllocatorFlags flags) {
|
||||
switch (flags.getKind()) {
|
||||
case CoroAllocatorKind::Stack:
|
||||
return nullptr;
|
||||
case CoroAllocatorKind::Async:
|
||||
return _swift_coro_task_allocator;
|
||||
case CoroAllocatorKind::Malloc:
|
||||
return _swift_coro_malloc_allocator;
|
||||
}
|
||||
}
|
||||
|
||||
static CoroAllocator CoroMallocAllocatorImpl{
|
||||
CoroAllocatorFlags(/*CoroAllocatorKind::Malloc*/ 2), malloc, free};
|
||||
|
||||
CoroAllocator *const swift::_swift_coro_malloc_allocator =
|
||||
&CoroMallocAllocatorImpl;
|
||||
|
||||
void *swift::swift_coro_alloc(CoroAllocator *allocator, size_t size) {
|
||||
return allocator->allocate(size);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,25 @@
|
||||
|
||||
// REQUIRES: swift_feature_CoroutineAccessors
|
||||
|
||||
// CHECK-LABEL: @"$s19coroutine_accessors1SV3irmSivxTwc" = {{.*}}global{{.*}} %swift.coro_func_pointer <{
|
||||
// : sub (
|
||||
// CHECK-SAME: $s19coroutine_accessors1SV3irmSivx
|
||||
// : $s19coroutine_accessors1SV3irmSivxTwc
|
||||
// : ),
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: }>
|
||||
|
||||
// CHECK-LABEL: _swift_coro_malloc_allocator = linkonce_odr hidden constant %swift.coro_allocator {
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: malloc,
|
||||
// CHECK-SAME: free
|
||||
// CHECK-SAME: }
|
||||
// CHECK-LABEL: _swift_coro_async_allocator = linkonce_odr hidden constant %swift.coro_allocator {
|
||||
// CHECK-SAME: i32 1,
|
||||
// CHECK-SAME: swift_task_alloc,
|
||||
// CHECK-SAME: swift_task_dealloc
|
||||
// CHECK-SAME: }
|
||||
|
||||
@frozen
|
||||
public struct S {
|
||||
public var o: any AnyObject
|
||||
@@ -26,4 +45,182 @@ public var irm: Int {
|
||||
yield &_i
|
||||
}
|
||||
} // public var irm
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @increment_irm(
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s19coroutine_accessors1SV3irmSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK-64: [[SIZE_64:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK-64: [[FRAME:%[^,]+]] = alloca i8, [[INT]] [[SIZE_64]]
|
||||
// CHECK-32: [[FRAME:%[^,]+]] = alloca i8, [[INT]] {{%[^,]+}}
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s19coroutine_accessors1SV3irmSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s19coroutine_accessors9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_irm")
|
||||
public mutating func increment_irm() {
|
||||
increment(&irm)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @increment_irm_async(
|
||||
// ptr swiftasync %0
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s19coroutine_accessors1SV3irmSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK-64: [[SIZE_64:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK-64: [[SIZE_1:%[^,]+]] = add [[INT]] [[SIZE_64]], 15
|
||||
// CHECK-32: [[SIZE_1:%[^,]+]] = add [[INT]] {{%[^,]+}}, 15
|
||||
// CHECK: [[SIZE:%[^,]+]] = and [[INT]] [[SIZE_1]], -16
|
||||
// CHECK: [[FRAME:%[^,]+]] = call swiftcc ptr @swift_task_alloc([[INT]] [[SIZE]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s19coroutine_accessors1SV3irmSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_async_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
|
||||
// increment_async([[YIELD]])
|
||||
|
||||
// CHECK: call swiftcc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_async_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call swiftcc void @swift_task_dealloc_through(ptr [[FRAME]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_irm_async")
|
||||
public mutating func increment_irm_async() async {
|
||||
await increment_async(&irm)
|
||||
}
|
||||
|
||||
public var force_yield_once_convention : () {
|
||||
_read {
|
||||
let nothing: () = ()
|
||||
yield nothing
|
||||
}
|
||||
// CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_irm_yield_once(
|
||||
// ptr noalias dereferenceable(32) %0
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// : $s19coroutine_accessors1SV3irmSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK-64: [[SIZE_64:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK-64: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i64(i64 [[SIZE_64]], i32 16)
|
||||
// CHECK-32: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i32(i32 {{%[^,]+}}, i32 16)
|
||||
// CHECK: [[FRAME:%[^,]+]] = call ptr @llvm.coro.alloca.get(token [[ALLOCATION]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s19coroutine_accessors1SV3irmSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s19coroutine_accessors9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call void @llvm.coro.alloca.free(token [[ALLOCATION]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_irm_yield_once")
|
||||
_modify {
|
||||
increment(&irm)
|
||||
|
||||
var nothing: () = ()
|
||||
yield ¬hing
|
||||
}
|
||||
}
|
||||
|
||||
public var force_yield_once_2_convention : () {
|
||||
read {
|
||||
let nothing: () = ()
|
||||
yield nothing
|
||||
}
|
||||
// CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_irm_yield_once_2(
|
||||
// ptr noalias %0
|
||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
||||
// ptr nocapture swiftself dereferenceable(16) %2
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s19coroutine_accessors1SV3irmSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK-64: [[SIZE_64:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK-64: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i64(i64 [[SIZE_64]], i32 16)
|
||||
// CHECK-32: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i32(i32 {{%[^,]+}}, i32 16)
|
||||
// CHECK: [[FRAME:%[^,]+]] = call ptr @llvm.coro.alloca.get(token [[ALLOCATION]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s19coroutine_accessors1SV3irmSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: [[ALLOCATOR]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s19coroutine_accessors9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: [[ALLOCATOR]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call void @llvm.coro.alloca.free(token [[ALLOCATION]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_irm_yield_once_2")
|
||||
modify {
|
||||
increment(&irm)
|
||||
|
||||
var nothing: () = ()
|
||||
yield ¬hing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func increment_async(_ int: inout Int) async {
|
||||
int += 1
|
||||
}
|
||||
|
||||
public func increment(_ int: inout Int) {
|
||||
int += 1
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// RUN: %target-swift-emit-irgen \
|
||||
// RUN: %s \
|
||||
// RUN: -Onone \
|
||||
// RUN: -enable-experimental-feature CoroutineAccessors \
|
||||
// RUN: -enable-arm64-corocc \
|
||||
// RUN: -enable-x86_64-corocc \
|
||||
@@ -8,6 +9,25 @@
|
||||
// REQUIRES: CPU=arm64 || CPU=arm64e || CPU=x86_64
|
||||
// REQUIRES: swift_feature_CoroutineAccessors
|
||||
|
||||
// CHECK-LABEL: @"$s27coroutine_accessors_popless1iSivxTwc" = {{.*}}global{{.*}} %swift.coro_func_pointer <{
|
||||
// : sub (
|
||||
// CHECK-SAME: $s27coroutine_accessors_popless1iSivx
|
||||
// : $s27coroutine_accessors_popless1iSivxTwc
|
||||
// : ),
|
||||
// CHECK-SAME: i32 0
|
||||
// CHECK-SAME: }>
|
||||
|
||||
// CHECK-LABEL: _swift_coro_async_allocator = linkonce_odr hidden constant %swift.coro_allocator {
|
||||
// CHECK-SAME: i32 1,
|
||||
// CHECK-SAME: swift_task_alloc,
|
||||
// CHECK-SAME: swift_task_dealloc
|
||||
// CHECK-SAME: }
|
||||
// CHECK-LABEL: _swift_coro_malloc_allocator = linkonce_odr hidden constant %swift.coro_allocator {
|
||||
// CHECK-SAME: i32 2,
|
||||
// CHECK-SAME: malloc,
|
||||
// CHECK-SAME: free
|
||||
// CHECK-SAME: }
|
||||
|
||||
// CHECK-LABEL: @__swift_coro_alloc_(
|
||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
|
||||
// CHECK-SAME: i64 [[SIZE:%[^)]+]]
|
||||
@@ -15,11 +35,11 @@
|
||||
// CHECK-SAME: {
|
||||
// CHECK: entry:
|
||||
// CHECK: [[USE_POPLESS:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
|
||||
// CHECK: br i1 [[USE_POPLESS]],
|
||||
// CHECK: br i1 [[USE_POPLESS]],
|
||||
// CHECK-SAME: label %coro.return.popless
|
||||
// CHECK-SAME: label %coro.return.normal
|
||||
// CHECK: coro.return.popless:
|
||||
// CHECK: [[STACK_ALLOCATION:%[^,]+]] = alloca i8, i64 [[SIZE]], align 16
|
||||
// CHECK: [[STACK_ALLOCATION:%[^,]+]] = alloca i8, i64 [[SIZE]]
|
||||
// CHECK: musttail call void @llvm.ret.popless()
|
||||
// CHECK: ret ptr [[STACK_ALLOCATION]]
|
||||
// CHECK: coro.return.normal:
|
||||
@@ -36,5 +56,180 @@ public var i: Int {
|
||||
read {
|
||||
yield _i
|
||||
}
|
||||
modify {
|
||||
yield &_i
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @increment_i(
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s27coroutine_accessors_popless1iSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK-64: [[SIZE_64:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK-64: [[FRAME:%[^,]+]] = alloca i8, [[INT]] [[SIZE_64]]
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s27coroutine_accessors_popless1iSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcorocc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: null
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s27coroutine_accessors_popless9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcorocc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: null
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_i")
|
||||
public func increment_i() {
|
||||
increment(&i)
|
||||
}
|
||||
|
||||
public func increment(_ int: inout Int) {
|
||||
int += 1
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @increment_i_async(
|
||||
// ptr swiftasync %0
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s27coroutine_accessors_popless1iSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK: [[SIZE_RAW:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK: [[SIZE_1:%[^,]+]] = add i64 [[SIZE_RAW]], 15
|
||||
// CHECK: [[SIZE:%[^,]+]] = and i64 [[SIZE_1]], -16
|
||||
// CHECK: [[FRAME:%[^,]+]] = call swiftcc ptr @swift_task_alloc(i64 [[SIZE]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s27coroutine_accessors_popless1iSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcorocc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_async_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
|
||||
// increment_async([[YIELD]])
|
||||
|
||||
// CHECK: call swiftcorocc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_async_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call swiftcc void @swift_task_dealloc_through(ptr [[FRAME]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_i_async")
|
||||
public func increment_i_async() async {
|
||||
await increment_async(&i)
|
||||
}
|
||||
|
||||
public func increment_async(_ int: inout Int) async {
|
||||
int += 1
|
||||
}
|
||||
|
||||
public var force_yield_once_convention : () {
|
||||
_read {
|
||||
let nothing: () = ()
|
||||
yield nothing
|
||||
}
|
||||
// CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_i_yield_once(
|
||||
// ptr noalias dereferenceable(32) %0
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s27coroutine_accessors_popless1iSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK: [[SIZE:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i64(i64 [[SIZE]], i32 16)
|
||||
// CHECK: [[FRAME:%[^,]+]] = call ptr @llvm.coro.alloca.get(token [[ALLOCATION]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s27coroutine_accessors_popless1iSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcorocc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s27coroutine_accessors_popless9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcorocc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: _swift_coro_malloc_allocator
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call void @llvm.coro.alloca.free(token [[ALLOCATION]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_i_yield_once")
|
||||
_modify {
|
||||
increment(&i)
|
||||
|
||||
var nothing: () = ()
|
||||
yield ¬hing
|
||||
}
|
||||
}
|
||||
|
||||
public var force_yield_once_2_convention : () {
|
||||
read {
|
||||
let nothing: () = ()
|
||||
yield nothing
|
||||
}
|
||||
// CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_i_yield_once_2(
|
||||
// ptr noalias %0
|
||||
// CHECK-SAME: ptr [[ALLOCATOR:%[^)]+]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK-SAME: {
|
||||
// : [[SIZE_32:%[^,]+]] = load i32
|
||||
// : ptr getelementptr inbounds (
|
||||
// : %swift.coro_func_pointer
|
||||
// CHECK: $s27coroutine_accessors_popless1iSivxTwc
|
||||
// : i32 0
|
||||
// : i32 1
|
||||
// : )
|
||||
// CHECK: [[SIZE:%[^,]+]] = zext i32 {{%[^,]+}} to i64
|
||||
// CHECK: [[ALLOCATION:%[^,]+]] = call token @llvm.coro.alloca.alloc.i64(i64 [[SIZE]], i32 16)
|
||||
// CHECK: [[FRAME:%[^,]+]] = call ptr @llvm.coro.alloca.get(token [[ALLOCATION]])
|
||||
// CHECK: call void @llvm.lifetime.start.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: [[RAMP:%[^,]+]] = call ptr @llvm.coro.prepare.retcon(ptr @"$s27coroutine_accessors_popless1iSivx")
|
||||
// CHECK: [[RETVAL:%[^,]+]] = call swiftcorocc { ptr, ptr } [[RAMP]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: [[ALLOCATOR]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: [[CONTINUATION:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 0
|
||||
// CHECK: [[YIELD:%[^,]+]] = extractvalue { ptr, ptr } [[RETVAL]], 1
|
||||
// CHECK: call swiftcc void @"$s27coroutine_accessors_popless9incrementyySizF"(
|
||||
// CHECK-SAME: [[YIELD]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call swiftcorocc void [[CONTINUATION]](
|
||||
// CHECK-SAME: [[FRAME]],
|
||||
// CHECK-SAME: [[ALLOCATOR]]
|
||||
// CHECK-SAME: )
|
||||
// CHECK: call void @llvm.lifetime.end.p0(i64 -1, ptr [[FRAME]])
|
||||
// CHECK: call void @llvm.coro.alloca.free(token [[ALLOCATION]])
|
||||
// CHECK: }
|
||||
@_silgen_name("increment_i_yield_once_2")
|
||||
modify {
|
||||
increment(&i)
|
||||
|
||||
var nothing: () = ()
|
||||
yield ¬hing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,11 +410,8 @@ Added: _$sScfsE25isIsolatingCurrentContextSbyF
|
||||
|
||||
// add callee-allocated coro entrypoints
|
||||
// TODO: CoroutineAccessors: several of these symbols should be in swiftCore
|
||||
Added: __swift_coro_malloc_allocator
|
||||
Added: __swift_coro_task_allocator
|
||||
Added: _swift_coro_alloc
|
||||
Added: _swift_coro_dealloc
|
||||
Added: _swift_coro_getGlobalAllocator
|
||||
Added: _swift_task_dealloc_through
|
||||
|
||||
// SwiftSettings
|
||||
|
||||
@@ -410,11 +410,8 @@ Added: _$sScfsE25isIsolatingCurrentContextSbyF
|
||||
|
||||
// add callee-allocated coro entrypoints
|
||||
// TODO: CoroutineAccessors: several of these symbols should be in swiftCore
|
||||
Added: __swift_coro_malloc_allocator
|
||||
Added: __swift_coro_task_allocator
|
||||
Added: _swift_coro_alloc
|
||||
Added: _swift_coro_dealloc
|
||||
Added: _swift_coro_getGlobalAllocator
|
||||
Added: _swift_task_dealloc_through
|
||||
|
||||
// SwiftSettings
|
||||
|
||||
Reference in New Issue
Block a user