From 24bb9bb73889dda135183ad9b17f44999fd37d81 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Thu, 6 Mar 2025 12:47:18 -0800 Subject: [PATCH] [CoroutineAccessors] Adopt swiftcoro param attr. --- lib/IRGen/GenCall.cpp | 21 ++++- lib/IRGen/GenDecl.cpp | 21 +++-- lib/IRGen/IRGenModule.h | 6 +- test/IRGen/coroutine_accessors.swift | 80 +++++++++++++++++++- test/IRGen/coroutine_accessors_popless.swift | 13 +++- 5 files changed, 126 insertions(+), 15 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index ec89cacb38630..8a5a9139c99c1 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -505,6 +505,13 @@ void IRGenModule::addSwiftSelfAttributes(llvm::AttributeList &attrs, attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); } +void IRGenModule::addSwiftCoroAttributes(llvm::AttributeList &attrs, + unsigned argIndex) { + llvm::AttrBuilder b(getLLVMContext()); + b.addAttribute(llvm::Attribute::SwiftCoro); + attrs = attrs.addParamAttributes(this->getLLVMContext(), argIndex, b); +} + void IRGenModule::addSwiftErrorAttributes(llvm::AttributeList &attrs, unsigned argIndex) { llvm::AttrBuilder b(getLLVMContext()); @@ -892,6 +899,7 @@ void SignatureExpansion::expandCoroutineContinuationParameters() { if (FnType->isCalleeAllocatedCoroutine()) { // Whether this is an unwind resumption. ParamIRTypes.push_back(IGM.CoroAllocatorPtrTy); + IGM.addSwiftCoroAttributes(Attrs, ParamIRTypes.size() - 1); } else { // Whether this is an unwind resumption. ParamIRTypes.push_back(IGM.Int1Ty); @@ -923,6 +931,7 @@ void SignatureExpansion::addCoroutineContextParameter() { void SignatureExpansion::addCoroutineAllocatorParameter() { ParamIRTypes.push_back(IGM.CoroAllocatorPtrTy); + IGM.addSwiftCoroAttributes(Attrs, ParamIRTypes.size() - 1); } NativeConventionSchema::NativeConventionSchema(IRGenModule &IGM, @@ -5170,7 +5179,11 @@ static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) { /*setIsNoInline=*/true, /*forPrologue=*/false, /*isPerformanceConstraint=*/false, - /*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC); + /*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC, + /*transformAttributes=*/ + [&IGM](llvm::AttributeList &attrs) { + IGM.addSwiftCoroAttributes(attrs, 0); + }); } static llvm::Constant *getCoroDeallocFn(IRGenModule &IGM) { @@ -5244,7 +5257,11 @@ static llvm::Constant *getCoroDeallocFn(IRGenModule &IGM) { /*setIsNoInline=*/true, /*forPrologue=*/false, /*isPerformanceConstraint=*/false, - /*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC); + /*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC, + /*transformAttributes=*/ + [&IGM](llvm::AttributeList &attrs) { + IGM.addSwiftCoroAttributes(attrs, 0); + }); } void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF, diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 731c9ce58b2aa..e08d5af96ae9a 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -6283,10 +6283,11 @@ IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) { } /// Should we be defining the given helper function? -static llvm::Function * -shouldDefineHelper(IRGenModule &IGM, llvm::Constant *fn, bool setIsNoInline, - IRLinkage *linkage, - std::optional specialCallingConv) { +static llvm::Function *shouldDefineHelper( + IRGenModule &IGM, llvm::Constant *fn, bool setIsNoInline, + IRLinkage *linkage, std::optional specialCallingConv, + std::optional> + transformAttrs) { auto *def = dyn_cast(fn); if (!def) return nullptr; if (!def->empty()) return nullptr; @@ -6301,6 +6302,12 @@ shouldDefineHelper(IRGenModule &IGM, llvm::Constant *fn, bool setIsNoInline, def->setCallingConv(specialCallingConv.value_or(IGM.DefaultCC)); if (setIsNoInline) def->addFnAttr(llvm::Attribute::NoInline); + + if (transformAttrs) { + auto attrs = def->getAttributes(); + (*transformAttrs)(attrs); + def->setAttributes(attrs); + } return def; } @@ -6317,7 +6324,9 @@ llvm::Constant *IRGenModule::getOrCreateHelperFunction( llvm::function_ref generate, bool setIsNoInline, bool forPrologue, bool isPerformanceConstraint, IRLinkage *optionalLinkageOverride, - std::optional specialCallingConv) { + std::optional specialCallingConv, + std::optional> + transformAttrs) { llvm::FunctionType *fnTy = llvm::FunctionType::get(resultTy, paramTys, false); @@ -6327,7 +6336,7 @@ llvm::Constant *IRGenModule::getOrCreateHelperFunction( if (llvm::Function *def = shouldDefineHelper(*this, fn, setIsNoInline, optionalLinkageOverride, - specialCallingConv)) { + specialCallingConv, transformAttrs)) { IRGenFunction IGF(*this, def, isPerformanceConstraint); if (DebugInfo && !forPrologue) DebugInfo->emitArtificialFunction(IGF, def); diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 419ebfd3d6f6c..93bf1f2172f78 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -1241,7 +1241,9 @@ class IRGenModule { bool setIsNoInline = false, bool forPrologue = false, bool isPerformanceConstraint = false, IRLinkage *optionalLinkage = nullptr, - std::optional specialCallingConv = std::nullopt); + std::optional specialCallingConv = std::nullopt, + std::optional> + transformAttrs = std::nullopt); llvm::Constant *getOrCreateRetainFunction(const TypeInfo &objectTI, SILType t, llvm::Type *llvmType, Atomicity atomicity); @@ -1947,6 +1949,8 @@ private: \ /// Add the swiftself attribute. void addSwiftSelfAttributes(llvm::AttributeList &attrs, unsigned argIndex); + void addSwiftCoroAttributes(llvm::AttributeList &attrs, unsigned argIndex); + void addSwiftAsyncContextAttributes(llvm::AttributeList &attrs, unsigned argIndex); diff --git a/test/IRGen/coroutine_accessors.swift b/test/IRGen/coroutine_accessors.swift index df44922fb5658..457ff1dde130d 100644 --- a/test/IRGen/coroutine_accessors.swift +++ b/test/IRGen/coroutine_accessors.swift @@ -5,6 +5,15 @@ // REQUIRES: swift_feature_CoroutineAccessors +// CHECK-LABEL: %T19coroutine_accessors1SV = type <{ %AnyObject, %TSi }> + +// CHECK-LABEL: @"$s19coroutine_accessors1SV3irmSivyTwc" = {{.*}}global %swift.coro_func_pointer +// : sub ( +// CHECK-SAME: $s19coroutine_accessors1SV3irmSivy +// : $s19coroutine_accessors1SV3irmSivyTwc +// : ) +// CHECK-SAME: i32 0 +// CHECK-SAME: }> // CHECK-LABEL: @"$s19coroutine_accessors1SV3irmSivxTwc" = {{.*}}global{{.*}} %swift.coro_func_pointer <{ // : sub ( // CHECK-SAME: $s19coroutine_accessors1SV3irmSivx @@ -25,7 +34,7 @@ // CHECK-SAME: } // CHECK-LABEL: @_swift_coro_alloc( -// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]] // CHECK-SAME: [[INT]] [[SIZE:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { @@ -40,7 +49,7 @@ // CHECK: } // CHECK-LABEL: @_swift_coro_dealloc( -// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]] // CHECK-SAME: ptr [[ADDRESS:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { @@ -73,16 +82,81 @@ public var o: any AnyObject public var _i: Int = 0 public var irm: Int { +// CHECK-LABEL: declare{{.*}} swiftcc void @"$s19coroutine_accessors1SVSiIetMIlYl_TC"(ptr noalias, ptr swiftcoro) + // CHECK-LABEL: define{{.*}} { ptr, {{i64|i32}} } @"$s19coroutine_accessors1SV3irmSivy"( +// CHECK-SAME: ptr noalias [[FRAME:%[^,]+]], +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]], +// CHECK-SAME: ptr [[S_FIELD_O:%[^,]+]], +// CHECK-SAME: [[INT]] [[S_FIELD__I:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { +// CHECK: [[ID:%[^,]+]] = call token @llvm.coro.id.retcon.once.dynamic( +// CHECK-SAME: i32 -1, +// CHECK-SAME: i32 16, +// CHECK-SAME: ptr @"$s19coroutine_accessors1SV3irmSivyTwc", +// CHECK-SAME: ptr [[ALLOCATOR]], +// CHECK-SAME: ptr [[FRAME]], +// CHECK-SAME: ptr @"$s19coroutine_accessors1SVSiIetMIgYy_TC", +// CHECK-SAME: ptr @_swift_coro_alloc, +// CHECK-SAME: ptr @_swift_coro_dealloc +// CHECK-SAME: ) +// CHECK: [[HANDLE:%[^,]+]] = call ptr @llvm.coro.begin( +// CHECK-SAME: token [[ID]], +// CHECK-SAME: ptr null +// CHECK-SAME: ) +// CHECK: call ptr (...) @llvm.coro.suspend.retcon.p0([[INT]] [[S_FIELD__I]]) +// CHECK: br i1 false, label %[[UNWIND:[^,]+]], label %[[NORMAL:[^,]+]] +// CHECK: [[NORMAL]]: +// CHECK: br label %coro.end +// CHECK: [[UNWIND]]: +// CHECK: br label %coro.end +// CHECK: coro.end: +// CHECK: call i1 @llvm.coro.end( +// CHECK-SAME: ptr [[HANDLE]], +// CHECK-SAME: i1 false, +// CHECK-SAME: token none +// CHECK-SAME: ) +// CHECK: unreachable // CHECK: } read { yield _i } // CHECK-LABEL: define{{.*}} { ptr, ptr } @"$s19coroutine_accessors1SV3irmSivx"( +// CHECK-SAME: ptr noalias [[FRAME:%[^,]+]], +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]], +// CHECK-SAME: ptr nocapture swiftself dereferenceable({{8|16}}) [[SELF:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { +// CHECK: [[ID:%[^,]+]] = call token @llvm.coro.id.retcon.once.dynamic( +// CHECK-SAME: i32 -1, +// CHECK-SAME: i32 16, +// CHECK-SAME: ptr @"$s19coroutine_accessors1SV3irmSivxTwc", +// CHECK-SAME: ptr [[ALLOCATOR]], +// CHECK-SAME: ptr [[FRAME]], +// CHECK-SAME: ptr @"$s19coroutine_accessors1SVSiIetMIlYl_TC", +// CHECK-SAME: ptr @_swift_coro_alloc, +// CHECK-SAME: ptr @_swift_coro_dealloc +// CHECK-SAME: ) +// CHECK: [[HANDLE:%[^,]+]] = call ptr @llvm.coro.begin( +// CHECK-SAME: token [[ID]], +// CHECK-SAME: ptr null +// CHECK-SAME: ) +// CHECK: [[S_FIELD__I:%[^,]+]] = getelementptr inbounds %T19coroutine_accessors1SV, +// CHECK-SAME: ptr [[SELF]], +// CHECK-SAME: i32 0, +// CHECK-SAME: i32 1 +// CHECK: call ptr (...) @llvm.coro.suspend.retcon.p0( +// CHECK-SAME: ptr [[S_FIELD__I]] +// CHECK-SAME: ) +// CHECK: br i1 false, label %[[UNWIND:[^,]+]], label %[[NORMAL:[^,]+]] +// CHECK: [[NORMAL]]: +// CHECK: br label %coro.end +// CHECK: [[UNWIND]]: +// CHECK: br label %coro.end +// CHECK: coro.end: +// CHECK: [[REGISTER_8:%[^,]+]] = call i1 @llvm.coro.end(ptr [[HANDLE]], i1 false, token none) +// CHECK: unreachable // CHECK: } modify { yield &_i @@ -217,7 +291,7 @@ public var force_yield_once_2_convention : () { } // CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_irm_yield_once_2( // ptr noalias %0 -// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]] // ptr nocapture swiftself dereferenceable(16) %2 // CHECK-SAME: ) // CHECK-SAME: { diff --git a/test/IRGen/coroutine_accessors_popless.swift b/test/IRGen/coroutine_accessors_popless.swift index a089f3005c5f8..1109656a7a3d8 100644 --- a/test/IRGen/coroutine_accessors_popless.swift +++ b/test/IRGen/coroutine_accessors_popless.swift @@ -9,6 +9,13 @@ // REQUIRES: CPU=arm64 || CPU=arm64e || CPU=x86_64 // REQUIRES: swift_feature_CoroutineAccessors +// CHECK-LABEL: @"$s27coroutine_accessors_popless1iSivyTwc" = {{.*}}global{{.*}} %swift.coro_func_pointer <{ +// : sub ( +// CHECK-SAME: $s27coroutine_accessors_popless1iSivy +// : $s27coroutine_accessors_popless1iSivyTwc +// : ), +// CHECK-SAME: i32 0 +// CHECK-SAME: }> // CHECK-LABEL: @"$s27coroutine_accessors_popless1iSivxTwc" = {{.*}}global{{.*}} %swift.coro_func_pointer <{ // : sub ( // CHECK-SAME: $s27coroutine_accessors_popless1iSivx @@ -29,7 +36,7 @@ // CHECK-SAME: } // CHECK-LABEL: @_swift_coro_alloc( -// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]] // CHECK-SAME: i64 [[SIZE:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { @@ -53,7 +60,7 @@ // CHECK: } // CHECK-LABEL: @_swift_coro_dealloc( -// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^,]+]] // CHECK-SAME: ptr [[ADDRESS:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { @@ -231,7 +238,7 @@ public var force_yield_once_2_convention : () { } // CHECK-LABEL: define{{.*}} { ptr, ptr } @increment_i_yield_once_2( // ptr noalias %0 -// CHECK-SAME: ptr [[ALLOCATOR:%[^)]+]] +// CHECK-SAME: ptr swiftcoro [[ALLOCATOR:%[^)]+]] // CHECK-SAME: ) // CHECK-SAME: { // : [[SIZE_32:%[^,]+]] = load i32