Skip to content

Commit 061daa8

Browse files
authored
Merge pull request #36764 from nate-chandler/concurrency/irgen/rdar71376092
2 parents df86271 + 4d56b62 commit 061daa8

File tree

8 files changed

+84
-22
lines changed

8 files changed

+84
-22
lines changed

lib/IRGen/Callee.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ namespace irgen {
234234
/// The actual pointer, either to the function or to its descriptor.
235235
llvm::Value *Value;
236236

237+
/// An additional value whose meaning varies by the FunctionPointer's Kind:
238+
/// - Kind::AsyncFunctionPointer -> pointer to the corresponding function
239+
/// if the FunctionPointer was created via
240+
/// forDirect; nullptr otherwise.
241+
llvm::Value *SecondaryValue;
242+
237243
PointerAuthInfo AuthInfo;
238244

239245
Signature Sig;
@@ -243,9 +249,11 @@ namespace irgen {
243249
/// We may add more arguments to this; try to use the other
244250
/// constructors/factories if possible.
245251
explicit FunctionPointer(Kind kind, llvm::Value *value,
252+
llvm::Value *secondaryValue,
246253
PointerAuthInfo authInfo,
247254
const Signature &signature)
248-
: kind(kind), Value(value), AuthInfo(authInfo), Sig(signature) {
255+
: kind(kind), Value(value), SecondaryValue(secondaryValue),
256+
AuthInfo(authInfo), Sig(signature) {
249257
// The function pointer should have function type.
250258
assert(value->getType()->getPointerElementType()->isFunctionTy());
251259
// TODO: maybe assert similarity to signature.getType()?
@@ -258,18 +266,25 @@ namespace irgen {
258266
}
259267
}
260268

269+
explicit FunctionPointer(Kind kind, llvm::Value *value,
270+
PointerAuthInfo authInfo,
271+
const Signature &signature)
272+
: FunctionPointer(kind, value, nullptr, authInfo, signature){};
273+
261274
// Temporary only!
262275
explicit FunctionPointer(Kind kind, llvm::Value *value,
263276
const Signature &signature)
264277
: FunctionPointer(kind, value, PointerAuthInfo(), signature) {}
265278

266-
static FunctionPointer forDirect(IRGenModule &IGM,
267-
llvm::Constant *value,
279+
static FunctionPointer forDirect(IRGenModule &IGM, llvm::Constant *value,
280+
llvm::Constant *secondaryValue,
268281
CanSILFunctionType fnType);
269282

270283
static FunctionPointer forDirect(Kind kind, llvm::Constant *value,
284+
llvm::Constant *secondaryValue,
271285
const Signature &signature) {
272-
return FunctionPointer(kind, value, PointerAuthInfo(), signature);
286+
return FunctionPointer(kind, value, secondaryValue, PointerAuthInfo(),
287+
signature);
273288
}
274289

275290
static FunctionPointer forExplosionValue(IRGenFunction &IGF,
@@ -295,6 +310,13 @@ namespace irgen {
295310
/// Return the actual function pointer.
296311
llvm::Value *getRawPointer() const { return Value; }
297312

313+
/// Assuming that the receiver is of kind AsyncFunctionPointer, returns the
314+
/// pointer to the corresponding function if available.
315+
llvm::Value *getRawAsyncFunction() const {
316+
assert(kind.isAsyncFunctionPointer());
317+
return SecondaryValue;
318+
}
319+
298320
/// Given that this value is known to have been constructed from
299321
/// a direct function, return the function pointer.
300322
llvm::Constant *getDirectPointer() const {

lib/IRGen/GenCall.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,18 +1985,33 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
19851985
assert(functionPointer.getKind() != FunctionPointer::Kind::Function);
19861986
bool emitFunction = values.first;
19871987
bool emitSize = values.second;
1988-
auto *ptr = functionPointer.getRawPointer();
1989-
if (auto authInfo = functionPointer.getAuthInfo()) {
1990-
ptr = emitPointerAuthAuth(IGF, ptr, authInfo);
1991-
}
1992-
auto *afpPtr =
1993-
IGF.Builder.CreateBitCast(ptr, IGF.IGM.AsyncFunctionPointerPtrTy);
1988+
// Ensure that the AsyncFunctionPointer is not auth'd if it is not used and
1989+
// that it is not auth'd more than once if it is needed.
1990+
//
1991+
// The AsyncFunctionPointer is not needed in the case where only the function
1992+
// is being loaded and the FunctionPointer was created from a function_ref
1993+
// instruction.
1994+
llvm::Optional<llvm::Value *> afpPtrValue = llvm::None;
1995+
auto getAFPPtr = [&]() {
1996+
if (!afpPtrValue) {
1997+
auto *ptr = functionPointer.getRawPointer();
1998+
if (auto authInfo = functionPointer.getAuthInfo()) {
1999+
ptr = emitPointerAuthAuth(IGF, ptr, authInfo);
2000+
}
2001+
auto *afpPtr =
2002+
IGF.Builder.CreateBitCast(ptr, IGF.IGM.AsyncFunctionPointerPtrTy);
2003+
afpPtrValue = afpPtr;
2004+
}
2005+
return *afpPtrValue;
2006+
};
19942007
llvm::Value *fn = nullptr;
19952008
if (emitFunction) {
19962009
if (functionPointer.useStaticContextSize()) {
19972010
fn = functionPointer.getRawPointer();
2011+
} else if (auto *function = functionPointer.getRawAsyncFunction()) {
2012+
fn = function;
19982013
} else {
1999-
llvm::Value *addrPtr = IGF.Builder.CreateStructGEP(afpPtr, 0);
2014+
llvm::Value *addrPtr = IGF.Builder.CreateStructGEP(getAFPPtr(), 0);
20002015
fn = IGF.emitLoadOfRelativePointer(
20012016
Address(addrPtr, IGF.IGM.getPointerAlignment()), /*isFar*/ false,
20022017
/*expectedType*/ functionPointer.getFunctionType()->getPointerTo());
@@ -2014,7 +2029,7 @@ std::pair<llvm::Value *, llvm::Value *> irgen::getAsyncFunctionAndSize(
20142029
initialContextSize.getValue());
20152030
} else {
20162031
assert(!functionPointer.useStaticContextSize());
2017-
auto *sizePtr = IGF.Builder.CreateStructGEP(afpPtr, 1);
2032+
auto *sizePtr = IGF.Builder.CreateStructGEP(getAFPPtr(), 1);
20182033
size = IGF.Builder.CreateLoad(sizePtr, IGF.IGM.getPointerAlignment());
20192034
}
20202035
}
@@ -4667,8 +4682,9 @@ Callee irgen::getCFunctionPointerCallee(IRGenFunction &IGF,
46674682

46684683
FunctionPointer FunctionPointer::forDirect(IRGenModule &IGM,
46694684
llvm::Constant *fnPtr,
4685+
llvm::Constant *secondaryValue,
46704686
CanSILFunctionType fnType) {
4671-
return forDirect(fnType, fnPtr, IGM.getSignature(fnType));
4687+
return forDirect(fnType, fnPtr, secondaryValue, IGM.getSignature(fnType));
46724688
}
46734689

46744690
StringRef FunctionPointer::getName(IRGenModule &IGM) const {
@@ -4690,6 +4706,14 @@ llvm::Value *FunctionPointer::getPointer(IRGenFunction &IGF) const {
46904706
case BasicKind::Function:
46914707
return Value;
46924708
case BasicKind::AsyncFunctionPointer: {
4709+
if (auto *rawFunction = getRawAsyncFunction()) {
4710+
// If the pointer to the underlying function is available, it means that
4711+
// this FunctionPointer instance was created via
4712+
// FunctionPointer::forDirect and as such has no AuthInfo.
4713+
assert(!AuthInfo && "have PointerAuthInfo for an async FunctionPointer "
4714+
"for which the raw function is known");
4715+
return rawFunction;
4716+
}
46934717
auto *fnPtr = Value;
46944718
if (auto authInfo = AuthInfo) {
46954719
fnPtr = emitPointerAuthAuth(IGF, fnPtr, authInfo);

lib/IRGen/GenClass.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2653,7 +2653,15 @@ FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF,
26532653
case ClassMetadataLayout::MethodInfo::Kind::DirectImpl: {
26542654
auto fnPtr = llvm::ConstantExpr::getBitCast(methodInfo.getDirectImpl(),
26552655
signature.getType()->getPointerTo());
2656-
return FunctionPointer::forDirect(methodType, fnPtr, signature);
2656+
llvm::Constant *secondaryValue = nullptr;
2657+
if (cast<AbstractFunctionDecl>(method.getDecl())->hasAsync()) {
2658+
auto *silFn = IGF.IGM.getSILFunctionForAsyncFunctionPointer(
2659+
methodInfo.getDirectImpl());
2660+
secondaryValue = cast<llvm::Constant>(
2661+
IGF.IGM.getAddrOfSILFunction(silFn, NotForDefinition));
2662+
}
2663+
return FunctionPointer::forDirect(methodType, fnPtr, secondaryValue,
2664+
signature);
26572665
}
26582666
}
26592667

lib/IRGen/GenKeyPath.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,9 @@ getAccessorForComputedComponent(IRGenModule &IGM,
252252
&ignoreWitnessMetadata,
253253
forwardedArgs);
254254
}
255-
auto fnPtr = FunctionPointer::forDirect(IGM, accessorFn,
256-
accessor->getLoweredFunctionType());
255+
auto fnPtr =
256+
FunctionPointer::forDirect(IGM, accessorFn, /*secondaryValue*/ nullptr,
257+
accessor->getLoweredFunctionType());
257258
auto call = IGF.Builder.CreateCall(fnPtr, forwardedArgs.claimAll());
258259

259260
if (call->getType()->isVoidTy())

lib/IRGen/GenObjC.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,9 @@ Callee irgen::getObjCMethodCallee(IRGenFunction &IGF,
658658
Selector selector(method);
659659
llvm::Value *selectorValue = IGF.emitObjCSelectorRefLoad(selector.str());
660660

661-
auto fn = FunctionPointer::forDirect(FunctionPointer::Kind::Function,
662-
messenger, sig);
661+
auto fn =
662+
FunctionPointer::forDirect(FunctionPointer::Kind::Function, messenger,
663+
/*secondaryValue*/ nullptr, sig);
663664
return Callee(std::move(info), fn, receiverValue, selectorValue);
664665
}
665666

lib/IRGen/IRGenSIL.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,13 +2526,17 @@ void IRGenSILFunction::visitFunctionRefBaseInst(FunctionRefBaseInst *i) {
25262526
fn, NotForDefinition, false /*isDynamicallyReplaceableImplementation*/,
25272527
isa<PreviousDynamicFunctionRefInst>(i));
25282528
llvm::Constant *value;
2529+
llvm::Constant *secondaryValue;
25292530
if (fpKind.isAsyncFunctionPointer()) {
25302531
value = IGM.getAddrOfAsyncFunctionPointer(fn);
25312532
value = llvm::ConstantExpr::getBitCast(value, fnPtr->getType());
2533+
secondaryValue = IGM.getAddrOfSILFunction(fn, NotForDefinition);
25322534
} else {
25332535
value = fnPtr;
2536+
secondaryValue = nullptr;
25342537
}
2535-
FunctionPointer fp = FunctionPointer(fpKind, value, sig);
2538+
FunctionPointer fp =
2539+
FunctionPointer::forDirect(fpKind, value, secondaryValue, sig);
25362540

25372541
// Store the function as a FunctionPointer so we can avoid bitcasting
25382542
// or thunking if we don't need to.
@@ -6525,16 +6529,18 @@ void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) {
65256529
if (IGM.isResilient(conformance.getRequirement(),
65266530
ResilienceExpansion::Maximal)) {
65276531
llvm::Constant *fnPtr = IGM.getAddrOfDispatchThunk(member, NotForDefinition);
6532+
llvm::Constant *secondaryValue = nullptr;
65286533

65296534
if (fnType->isAsync()) {
6535+
secondaryValue = fnPtr;
65306536
auto *fnPtrType = fnPtr->getType();
65316537
fnPtr = IGM.getAddrOfAsyncFunctionPointer(
65326538
LinkEntity::forDispatchThunk(member));
65336539
fnPtr = llvm::ConstantExpr::getBitCast(fnPtr, fnPtrType);
65346540
}
65356541

65366542
auto sig = IGM.getSignature(fnType);
6537-
auto fn = FunctionPointer::forDirect(fnType, fnPtr, sig);
6543+
auto fn = FunctionPointer::forDirect(fnType, fnPtr, secondaryValue, sig);
65386544

65396545
setLoweredFunctionPointer(i, fn);
65406546
return;

test/Concurrency/Runtime/async_taskgroup_asynciterator_semantics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency -parse-as-library) | %FileCheck %s --dump-input=always
22
// REQUIRES: executable_test
33
// REQUIRES: concurrency
4-
// XFAIL: linux
4+
// UNSUPPORTED: linux
55
// XFAIL: windows
66

77
struct Boom: Error {}

test/Concurrency/Runtime/async_taskgroup_is_asyncsequence.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// rdar://76038845
77
// UNSUPPORTED: use_os_stdlib
88

9-
// XFAIL: linux
9+
// UNSUPPORTED: linux
1010
// XFAIL: windows
1111

1212
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)

0 commit comments

Comments
 (0)