Skip to content

Commit 8535e80

Browse files
Merge pull request #61459 from aschwaighofer/opaque_ptr_part_2
IRGen: More fixes for LLVM's opaque pointers
2 parents d6bfdbf + 15015c0 commit 8535e80

15 files changed

+132
-65
lines changed

lib/IRGen/Callee.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ namespace irgen {
317317
// If this is an await function pointer contains the signature of the await
318318
// call (without return values).
319319
llvm::Type *awaitSignature = nullptr;
320+
bool useSignature = false;
320321

321322
explicit FunctionPointer(Kind kind, llvm::Value *value,
322323
const Signature &signature)
@@ -364,14 +365,28 @@ namespace irgen {
364365
}
365366

366367
static FunctionPointer createSigned(Kind kind, llvm::Value *value,
368+
PointerAuthInfo authInfo,
369+
const Signature &signature,
370+
bool useSignature = false) {
371+
auto res = FunctionPointer(kind, value, authInfo, signature);
372+
res.useSignature = useSignature;
373+
return res;
374+
}
375+
static FunctionPointer createSignedClosure(Kind kind, llvm::Value *value,
367376
PointerAuthInfo authInfo,
368377
const Signature &signature) {
369-
return FunctionPointer(kind, value, authInfo, signature);
378+
auto res = FunctionPointer(kind, value, authInfo, signature);
379+
res.useSignature = true;
380+
return res;
370381
}
371382

383+
372384
static FunctionPointer createUnsigned(Kind kind, llvm::Value *value,
373-
const Signature &signature) {
374-
return FunctionPointer(kind, value, signature);
385+
const Signature &signature,
386+
bool useSignature = false) {
387+
auto res = FunctionPointer(kind, value, signature);
388+
res.useSignature = useSignature;
389+
return res;
375390
}
376391

377392
static FunctionPointer forDirect(IRGenModule &IGM, llvm::Constant *value,
@@ -380,9 +395,12 @@ namespace irgen {
380395

381396
static FunctionPointer forDirect(Kind kind, llvm::Constant *value,
382397
llvm::Constant *secondaryValue,
383-
const Signature &signature) {
384-
return FunctionPointer(kind, value, secondaryValue, PointerAuthInfo(),
398+
const Signature &signature,
399+
bool useSignature = false) {
400+
auto res = FunctionPointer(kind, value, secondaryValue, PointerAuthInfo(),
385401
signature);
402+
res.useSignature = useSignature;
403+
return res;
386404
}
387405

388406
static FunctionPointer forExplosionValue(IRGenFunction &IGF,

lib/IRGen/GenCall.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5014,13 +5014,13 @@ Callee irgen::getBlockPointerCallee(IRGenFunction &IGF,
50145014

50155015
Callee irgen::getSwiftFunctionPointerCallee(
50165016
IRGenFunction &IGF, llvm::Value *fnPtr, llvm::Value *dataPtr,
5017-
CalleeInfo &&calleeInfo, bool castOpaqueToRefcountedContext) {
5017+
CalleeInfo &&calleeInfo, bool castOpaqueToRefcountedContext, bool isClosure) {
50185018
auto sig = emitCastOfFunctionPointer(IGF, fnPtr, calleeInfo.OrigFnType);
50195019
auto authInfo =
50205020
PointerAuthInfo::forFunctionPointer(IGF.IGM, calleeInfo.OrigFnType);
50215021

5022-
auto fn = FunctionPointer::createSigned(calleeInfo.OrigFnType, fnPtr,
5023-
authInfo, sig);
5022+
auto fn = isClosure ? FunctionPointer::createSignedClosure(calleeInfo.OrigFnType, fnPtr, authInfo, sig) :
5023+
FunctionPointer::createSigned(calleeInfo.OrigFnType, fnPtr, authInfo, sig);
50245024
if (castOpaqueToRefcountedContext) {
50255025
assert(dataPtr && dataPtr->getType() == IGF.IGM.OpaquePtrTy &&
50265026
"Expecting trivial closure context");
@@ -5054,11 +5054,18 @@ StringRef FunctionPointer::getName(IRGenModule &IGM) const {
50545054
switch (getBasicKind()) {
50555055
case BasicKind::Function:
50565056
return getRawPointer()->getName();
5057-
case BasicKind::AsyncFunctionPointer:
5057+
case BasicKind::AsyncFunctionPointer: {
5058+
auto *asyncFnPtr = getDirectPointer();
5059+
// Handle windows style async function pointers.
5060+
if (auto *ce = dyn_cast<llvm::ConstantExpr>(asyncFnPtr)) {
5061+
if (ce->getOpcode() == llvm::Instruction::IntToPtr) {
5062+
asyncFnPtr = cast<llvm::Constant>(asyncFnPtr->getOperand(0));
5063+
}
5064+
}
5065+
asyncFnPtr = cast<llvm::Constant>(asyncFnPtr->stripPointerCasts());
50585066
return IGM
5059-
.getSILFunctionForAsyncFunctionPointer(
5060-
cast<llvm::Constant>(getDirectPointer()->getOperand(0)))
5061-
->getName();
5067+
.getSILFunctionForAsyncFunctionPointer(asyncFnPtr)->getName();
5068+
}
50625069
}
50635070
llvm_unreachable("unhandled case");
50645071
}
@@ -5341,6 +5348,13 @@ void irgen::forwardAsyncCallResult(IRGenFunction &IGF,
53415348
}
53425349

53435350
llvm::FunctionType *FunctionPointer::getFunctionType() const {
5351+
// Static async function pointers can read the type off the secondary value
5352+
// (the function definition.
5353+
if (SecondaryValue) {
5354+
assert(kind == FunctionPointer::Kind::AsyncFunctionPointer);
5355+
return cast<llvm::Function>(SecondaryValue)->getFunctionType();
5356+
}
5357+
53445358
// Read the function type off the global or else from the Signature.
53455359
if (auto *constant = dyn_cast<llvm::Constant>(Value)) {
53465360
auto *gv = dyn_cast<llvm::GlobalValue>(Value);
@@ -5349,6 +5363,15 @@ llvm::FunctionType *FunctionPointer::getFunctionType() const {
53495363
->isOpaqueOrPointeeTypeMatches(Sig.getType()));
53505364
return Sig.getType();
53515365
}
5366+
5367+
if (useSignature) { // Because of various casting (e.g thin_to_thick) the
5368+
// signature of the function Value might mismatch
5369+
// (e.g no context argument).
5370+
assert(llvm::cast<llvm::PointerType>(Value->getType())
5371+
->isOpaqueOrPointeeTypeMatches(Sig.getType()));
5372+
return Sig.getType();
5373+
}
5374+
53525375
assert(llvm::cast<llvm::PointerType>(Value->getType())
53535376
->isOpaqueOrPointeeTypeMatches(gv->getValueType()));
53545377
return cast<llvm::FunctionType>(gv->getValueType());

lib/IRGen/GenCall.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ namespace irgen {
198198
llvm::Value *fnPtr,
199199
llvm::Value *contextPtr,
200200
CalleeInfo &&info,
201-
bool castOpaqueToRefcountedContext);
201+
bool castOpaqueToRefcountedContext,
202+
bool isClosure);
202203

203204
Address emitAllocYieldOnceCoroutineBuffer(IRGenFunction &IGF);
204205
void emitDeallocYieldOnceCoroutineBuffer(IRGenFunction &IGF, Address buffer);

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2871,7 +2871,7 @@ FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF,
28712871
auto authInfo =
28722872
PointerAuthInfo::emit(IGF, schema, slot.getAddress(), method);
28732873
return FunctionPointer::createSigned(methodType, fnPtr, authInfo,
2874-
signature);
2874+
signature, true);
28752875
}
28762876
case ClassMetadataLayout::MethodInfo::Kind::DirectImpl: {
28772877
auto fnPtr = llvm::ConstantExpr::getBitCast(methodInfo.getDirectImpl(),
@@ -2884,7 +2884,7 @@ FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF,
28842884
IGF.IGM.getAddrOfSILFunction(silFn, NotForDefinition));
28852885
}
28862886
return FunctionPointer::forDirect(methodType, fnPtr, secondaryValue,
2887-
signature);
2887+
signature, true);
28882888
}
28892889
}
28902890
llvm_unreachable("covered switch");

lib/IRGen/GenEnum.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ unsigned EnumImplStrategy::getPayloadSizeForMetadata() const {
183183
llvm_unreachable("don't need payload size for this enum kind");
184184
}
185185

186-
llvm::Value *EnumImplStrategy::
186+
LoadedRef EnumImplStrategy::
187187
loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc, Address addr) const {
188188
IGF.IGM.error(loc, "Can only load from an address of an optional "
189189
"reference.");
@@ -2803,13 +2803,11 @@ namespace {
28032803
}
28042804
}
28052805

2806-
llvm::Value *loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
2806+
LoadedRef loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
28072807
Address addr) const override {
28082808
// There is no need to bitcast from the enum address. Loading from the
28092809
// reference type emits a bitcast to the proper reference type first.
2810-
return getLoadablePayloadTypeInfo()
2811-
.loadRefcountedPtr(IGF, loc, addr)
2812-
.getValue();
2810+
return getLoadablePayloadTypeInfo().loadRefcountedPtr(IGF, loc, addr);
28132811
}
28142812
private:
28152813
llvm::ConstantInt *getZeroExtraTagConstant(IRGenModule &IGM) const {

lib/IRGen/GenEnum.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_IRGEN_GENENUM_H
1515

1616
#include "TypeInfo.h"
17+
#include "LoadableTypeInfo.h"
1718

1819
namespace llvm {
1920
class BasicBlock;
@@ -441,8 +442,8 @@ class EnumImplStrategy {
441442
virtual bool needsPayloadSizeInMetadata() const = 0;
442443
virtual unsigned getPayloadSizeForMetadata() const;
443444

444-
virtual llvm::Value *loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
445-
Address addr) const;
445+
virtual LoadedRef loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
446+
Address addr) const;
446447

447448
void callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
448449
SILType T, IsInitialization_t isInit,

lib/IRGen/GenExistential.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ class ClassExistentialTypeInfo final
12661266
LoadedRef loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
12671267
Address existential) const override {
12681268
Address valueAddr = projectValue(IGF, existential);
1269-
return LoadedRef(IGF.emitLoadRefcountedPtr(valueAddr, Refcounting), true);
1269+
return LoadedRef(IGF.emitLoadRefcountedPtr(valueAddr, Refcounting), true, Refcounting);
12701270
}
12711271

12721272
llvm::StructType *buildReferenceStorageType(IRGenModule &IGM,

lib/IRGen/GenHeap.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,17 +1345,31 @@ llvm::Value *IRGenFunction::emitLoadRefcountedPtr(Address addr,
13451345
}
13461346

13471347
llvm::Value *IRGenFunction::
1348-
emitIsUniqueCall(llvm::Value *value, SourceLoc loc, bool isNonNull) {
1348+
emitIsUniqueCall(llvm::Value *value, ReferenceCounting style, SourceLoc loc, bool isNonNull) {
13491349
FunctionPointer fn;
13501350
bool nonObjC = !IGM.getAvailabilityContext().isContainedIn(
13511351
IGM.Context.getObjCIsUniquelyReferencedAvailability());
1352-
1353-
if (value->getType() == IGM.RefCountedPtrTy) {
1352+
switch (style) {
1353+
case ReferenceCounting::Native: {
13541354
if (isNonNull)
13551355
fn = IGM.getIsUniquelyReferenced_nonNull_nativeFunctionPointer();
13561356
else
13571357
fn = IGM.getIsUniquelyReferenced_nativeFunctionPointer();
1358-
} else if (value->getType() == IGM.UnknownRefCountedPtrTy) {
1358+
}
1359+
break;
1360+
case ReferenceCounting::Bridge: {
1361+
if (!isNonNull)
1362+
unimplemented(loc, "optional bridge ref");
1363+
1364+
if (nonObjC)
1365+
fn =
1366+
IGM.getIsUniquelyReferencedNonObjC_nonNull_bridgeObjectFunctionPointer();
1367+
else
1368+
fn = IGM.getIsUniquelyReferenced_nonNull_bridgeObjectFunctionPointer();
1369+
}
1370+
break;
1371+
case ReferenceCounting::ObjC:
1372+
case ReferenceCounting::Unknown: {
13591373
if (nonObjC) {
13601374
if (isNonNull)
13611375
fn = IGM.getIsUniquelyReferencedNonObjC_nonNullFunctionPointer();
@@ -1367,18 +1381,15 @@ emitIsUniqueCall(llvm::Value *value, SourceLoc loc, bool isNonNull) {
13671381
else
13681382
fn = IGM.getIsUniquelyReferencedFunctionPointer();
13691383
}
1370-
} else if (value->getType() == IGM.BridgeObjectPtrTy) {
1371-
if (!isNonNull)
1372-
unimplemented(loc, "optional bridge ref");
1373-
1374-
if (nonObjC)
1375-
fn =
1376-
IGM.getIsUniquelyReferencedNonObjC_nonNull_bridgeObjectFunctionPointer();
1377-
else
1378-
fn = IGM.getIsUniquelyReferenced_nonNull_bridgeObjectFunctionPointer();
1379-
} else {
1384+
}
1385+
break;
1386+
case ReferenceCounting::Error:
1387+
case ReferenceCounting::Block:
1388+
case ReferenceCounting::Custom:
1389+
case ReferenceCounting::None:
13801390
llvm_unreachable("Unexpected LLVM type for a refcounted pointer.");
13811391
}
1392+
13821393
llvm::CallInst *call = Builder.CreateCall(fn, value);
13831394
call->setDoesNotThrow();
13841395
return call;

lib/IRGen/GenObjC.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,8 @@ Callee irgen::getObjCMethodCallee(IRGenFunction &IGF,
664664

665665
auto fn =
666666
FunctionPointer::forDirect(FunctionPointer::Kind::Function, messenger,
667-
/*secondaryValue*/ nullptr, sig);
667+
/*secondaryValue*/ nullptr, sig,
668+
/*useSignature*/ true);
668669
return Callee(std::move(info), fn, receiverValue, selectorValue);
669670
}
670671

lib/IRGen/GenStruct.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,12 @@ namespace {
480480
clangFnAddr = emitCXXConstructorThunkIfNeeded(
481481
IGF.IGM, signature, copyConstructor, name, clangFnAddr);
482482
callee = cast<llvm::Function>(clangFnAddr);
483-
dest = IGF.coerceValue(dest, callee->getFunctionType()->getParamType(0),
484-
IGF.IGM.DataLayout);
485-
src = IGF.coerceValue(src, callee->getFunctionType()->getParamType(1),
486-
IGF.IGM.DataLayout);
483+
if (IGF.IGM.getLLVMContext().supportsTypedPointers()) {
484+
dest = IGF.coerceValue(dest, callee->getFunctionType()->getParamType(0),
485+
IGF.IGM.DataLayout);
486+
src = IGF.coerceValue(src, callee->getFunctionType()->getParamType(1),
487+
IGF.IGM.DataLayout);
488+
}
487489
IGF.Builder.CreateCall(callee->getFunctionType(), callee, {dest, src});
488490
}
489491

@@ -532,9 +534,11 @@ namespace {
532534
destructorGlobalDecl, NotForDefinition));
533535

534536
SmallVector<llvm::Value *, 2> args;
535-
auto *thisArg = IGF.coerceValue(address.getAddress(),
536-
destructorFnAddr->getArg(0)->getType(),
537-
IGF.IGM.DataLayout);
537+
auto *thisArg = address.getAddress();
538+
if (IGF.IGM.getLLVMContext().supportsTypedPointers())
539+
thisArg = IGF.coerceValue(address.getAddress(),
540+
destructorFnAddr->getArg(0)->getType(),
541+
IGF.IGM.DataLayout);
538542
args.push_back(thisArg);
539543
llvm::Value *implicitParam =
540544
clang::CodeGen::getCXXDestructorImplicitParam(

lib/IRGen/HeapTypeInfo.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,10 @@ class HeapTypeInfo
234234

235235
LoadedRef loadRefcountedPtr(IRGenFunction &IGF, SourceLoc loc,
236236
Address addr) const override {
237+
auto style = asDerived().getReferenceCounting();
237238
llvm::Value *ptr =
238-
IGF.emitLoadRefcountedPtr(addr, asDerived().getReferenceCounting());
239-
return LoadedRef(ptr, true);
239+
IGF.emitLoadRefcountedPtr(addr, style);
240+
return LoadedRef(ptr, true, style);
240241
}
241242

242243
ReferenceCounting getReferenceCountingType() const override {

lib/IRGen/IRGenFunction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,8 @@ class IRGenFunction {
522522
void emitErrorStrongRetain(llvm::Value *value);
523523
void emitErrorStrongRelease(llvm::Value *value);
524524

525-
llvm::Value *emitIsUniqueCall(llvm::Value *value, SourceLoc loc,
526-
bool isNonNull);
525+
llvm::Value *emitIsUniqueCall(llvm::Value *value, ReferenceCounting style,
526+
SourceLoc loc, bool isNonNull);
527527

528528
llvm::Value *emitIsEscapingClosureCall(llvm::Value *value, SourceLoc loc,
529529
unsigned verificationType);

0 commit comments

Comments
 (0)