From 2802541d9580b3901ce75710802d0dad50aff0e1 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Mon, 27 Mar 2023 07:23:01 -0700 Subject: [PATCH] [5.9] IRGen: Don't directly call async functions that have weak/linkonce_odr linkage The async function pointer context size and the async function implementiation are logically tied. Using a different async context pointer context size and async function implementation (from different translation units) is problematic. rdar://106029807 Original PR: #64638 --- lib/IRGen/IRGenSIL.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 56b8a8a26c467..6a1e0fe1234f6 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -2715,6 +2715,18 @@ FunctionPointer::Kind irgen::classifyFunctionPointerKind(SILFunction *fn) { return fn->getLoweredFunctionType(); } +// Async functions that end up with weak_odr or linkonce_odr linkage may not be +// directly called because we need to preserve the connection between the +// function's implementation and the function's context size in the async +// function pointer data structure. +static bool mayDirectlyCallAsync(SILFunction *fn) { + if (fn->getLinkage() == SILLinkage::Shared || + fn->getLinkage() == SILLinkage::PublicNonABI) { + return false; + } + + return true; +} void IRGenSILFunction::visitFunctionRefBaseInst(FunctionRefBaseInst *i) { auto fn = i->getInitiallyReferencedFunction(); @@ -2741,7 +2753,8 @@ void IRGenSILFunction::visitFunctionRefBaseInst(FunctionRefBaseInst *i) { if (fpKind.isAsyncFunctionPointer()) { value = IGM.getAddrOfAsyncFunctionPointer(fn); value = llvm::ConstantExpr::getBitCast(value, fnPtr->getType()); - secondaryValue = IGM.getAddrOfSILFunction(fn, NotForDefinition); + secondaryValue = mayDirectlyCallAsync(fn) ? + IGM.getAddrOfSILFunction(fn, NotForDefinition) : nullptr; // For ordinary sync functions and special async functions, produce // only the direct address of the function. The runtime does not