Skip to content

Commit 4021082

Browse files
committed
[wip][cxx-interop] Support for custom reference counting operations.
1 parent c6cea1e commit 4021082

19 files changed

+279
-18
lines changed

include/swift/AST/Decl.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4231,15 +4231,7 @@ class ClassDecl final : public NominalTypeDecl {
42314231

42324232
/// Whether the class uses the ObjC object model (reference counting,
42334233
/// allocation, etc.), the Swift model, or has no reference counting at all.
4234-
ReferenceCounting getObjectModel() const {
4235-
if (isForeignReferenceType())
4236-
return ReferenceCounting::None;
4237-
4238-
if (checkAncestry(AncestryFlags::ObjCObjectModel))
4239-
return ReferenceCounting::ObjC;
4240-
4241-
return ReferenceCounting::Native;
4242-
}
4234+
ReferenceCounting getObjectModel() const;
42434235

42444236
LayoutConstraintKind getLayoutConstraintKind() const {
42454237
if (getObjectModel() == ReferenceCounting::ObjC)
@@ -4353,6 +4345,8 @@ class ClassDecl final : public NominalTypeDecl {
43534345
/// non-reference-counted swift reference type that was imported from a C++
43544346
/// record.
43554347
bool isForeignReferenceType() const;
4348+
4349+
bool hasRefCountingAnnotations() const;
43564350
};
43574351

43584352
/// The set of known protocols for which derived conformances are supported.

include/swift/AST/ReferenceCounting.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ enum class ReferenceCounting : uint8_t {
3333
/// types.
3434
None,
3535

36+
/// The object uses swift_attr("retain:XXX") and "release:XXX" to implement
37+
/// reference counting.
38+
CxxCustom,
39+
3640
/// The object uses _Block_copy/_Block_release reference counting.
3741
///
3842
/// This is a strict subset of ObjC; all blocks are also ObjC reference

lib/AST/Decl.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5227,6 +5227,40 @@ bool ClassDecl::isForeignReferenceType() const {
52275227
return getClangDecl() && isa<clang::RecordDecl>(getClangDecl());
52285228
}
52295229

5230+
bool ClassDecl::hasRefCountingAnnotations() const {
5231+
auto decl = dyn_cast_or_null<clang::RecordDecl>(getClangDecl());
5232+
if (!decl)
5233+
return false;
5234+
5235+
bool hasRetain = decl->hasAttrs() && llvm::any_of(decl->getAttrs(),
5236+
[](auto *attr) {
5237+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
5238+
return swiftAttr->getAttribute().startswith("retain:");
5239+
return false;
5240+
});
5241+
5242+
bool hasRelease = decl->hasAttrs() && llvm::any_of(decl->getAttrs(),
5243+
[](auto *attr) {
5244+
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
5245+
return swiftAttr->getAttribute().startswith("release:");
5246+
return false;
5247+
});
5248+
5249+
return hasRetain && hasRelease;
5250+
}
5251+
5252+
ReferenceCounting ClassDecl::getObjectModel() const {
5253+
if (isForeignReferenceType())
5254+
return hasRefCountingAnnotations()
5255+
? ReferenceCounting::CxxCustom
5256+
: ReferenceCounting::None;
5257+
5258+
if (checkAncestry(AncestryFlags::ObjCObjectModel))
5259+
return ReferenceCounting::ObjC;
5260+
5261+
return ReferenceCounting::Native;
5262+
}
5263+
52305264
EnumCaseDecl *EnumCaseDecl::create(SourceLoc CaseLoc,
52315265
ArrayRef<EnumElementDecl *> Elements,
52325266
DeclContext *DC) {

lib/AST/Type.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6037,12 +6037,16 @@ ReferenceCounting TypeBase::getReferenceCounting() {
60376037
CanType type = getCanonicalType();
60386038
ASTContext &ctx = type->getASTContext();
60396039

6040+
if (isForeignReferenceType())
6041+
return lookThroughAllOptionalTypes()
6042+
->getClassOrBoundGenericClass()
6043+
->hasRefCountingAnnotations()
6044+
? ReferenceCounting::CxxCustom
6045+
: ReferenceCounting::None;
6046+
60406047
// In the absence of Objective-C interoperability, everything uses native
60416048
// reference counting or is the builtin BridgeObject.
60426049
if (!ctx.LangOpts.EnableObjCInterop) {
6043-
if (isForeignReferenceType())
6044-
return ReferenceCounting::None;
6045-
60466050
return type->getKind() == TypeKind::BuiltinBridgeObject
60476051
? ReferenceCounting::Bridge
60486052
: ReferenceCounting::Native;

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ namespace {
148148
HeaderSize = CurSize;
149149
break;
150150
case ReferenceCounting::None:
151+
case ReferenceCounting::CxxCustom:
151152
break;
152153
case ReferenceCounting::Block:
153154
case ReferenceCounting::Unknown:

lib/IRGen/GenHeap.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ unsigned IRGenModule::getReferenceStorageExtraInhabitantCount(
589589
case ReferenceCounting::ObjC:
590590
case ReferenceCounting::None:
591591
case ReferenceCounting::Unknown:
592+
case ReferenceCounting::CxxCustom:
592593
break;
593594
case ReferenceCounting::Bridge:
594595
case ReferenceCounting::Error:
@@ -618,6 +619,7 @@ SpareBitVector IRGenModule::getReferenceStorageSpareBits(
618619
case ReferenceCounting::Block:
619620
case ReferenceCounting::ObjC:
620621
case ReferenceCounting::None:
622+
case ReferenceCounting::CxxCustom:
621623
case ReferenceCounting::Unknown:
622624
break;
623625
case ReferenceCounting::Bridge:
@@ -648,6 +650,7 @@ APInt IRGenModule::getReferenceStorageExtraInhabitantValue(unsigned bits,
648650
case ReferenceCounting::Block:
649651
case ReferenceCounting::ObjC:
650652
case ReferenceCounting::None:
653+
case ReferenceCounting::CxxCustom:
651654
case ReferenceCounting::Unknown:
652655
break;
653656
case ReferenceCounting::Bridge:
@@ -669,6 +672,7 @@ APInt IRGenModule::getReferenceStorageExtraInhabitantMask(
669672
case ReferenceCounting::Block:
670673
case ReferenceCounting::ObjC:
671674
case ReferenceCounting::None:
675+
case ReferenceCounting::CxxCustom:
672676
case ReferenceCounting::Unknown:
673677
break;
674678
case ReferenceCounting::Bridge:
@@ -689,6 +693,7 @@ llvm::Value *IRGenFunction::getReferenceStorageExtraInhabitantIndex(Address src,
689693
case ReferenceCounting::Block:
690694
case ReferenceCounting::ObjC:
691695
case ReferenceCounting::None:
696+
case ReferenceCounting::CxxCustom:
692697
case ReferenceCounting::Unknown:
693698
break;
694699
case ReferenceCounting::Bridge:
@@ -726,6 +731,7 @@ void IRGenFunction::storeReferenceStorageExtraInhabitant(llvm::Value *index,
726731
case ReferenceCounting::Block:
727732
case ReferenceCounting::ObjC:
728733
case ReferenceCounting::None:
734+
case ReferenceCounting::CxxCustom:
729735
case ReferenceCounting::Unknown:
730736
break;
731737
case ReferenceCounting::Bridge:
@@ -760,6 +766,7 @@ void IRGenFunction::storeReferenceStorageExtraInhabitant(llvm::Value *index,
760766
std::move(spareBits), isOptional); \
761767
case ReferenceCounting::ObjC: \
762768
case ReferenceCounting::None: \
769+
case ReferenceCounting::CxxCustom: \
763770
case ReferenceCounting::Block: \
764771
case ReferenceCounting::Unknown: \
765772
return new Unknown##Name##ReferenceTypeInfo( \
@@ -1015,6 +1022,8 @@ void IRGenFunction::emitStrongRelease(llvm::Value *value,
10151022
return emitBridgeStrongRelease(value, atomicity);
10161023
case ReferenceCounting::Error:
10171024
return emitErrorStrongRelease(value);
1025+
case ReferenceCounting::CxxCustom:
1026+
llvm_unreachable("Ref counting should be handled in TypeInfo.");
10181027
case ReferenceCounting::None:
10191028
return; // This is a no-op if we don't have any ref-counting.
10201029
}
@@ -1042,6 +1051,8 @@ void IRGenFunction::emitStrongRetain(llvm::Value *value,
10421051
case ReferenceCounting::Error:
10431052
emitErrorStrongRetain(value);
10441053
return;
1054+
case ReferenceCounting::CxxCustom:
1055+
llvm_unreachable("Ref counting should be handled in TypeInfo.");
10451056
case ReferenceCounting::None:
10461057
return; // This is a no-op if we don't have any ref-counting.
10471058
}
@@ -1061,6 +1072,7 @@ llvm::Type *IRGenModule::getReferenceType(ReferenceCounting refcounting) {
10611072
return UnknownRefCountedPtrTy;
10621073
case ReferenceCounting::Error:
10631074
return ErrorPtrTy;
1075+
case ReferenceCounting::CxxCustom:
10641076
case ReferenceCounting::None:
10651077
return OpaquePtrTy;
10661078
}
@@ -1080,6 +1092,7 @@ llvm::Type *IRGenModule::getReferenceType(ReferenceCounting refcounting) {
10801092
case ReferenceCounting::Bridge: \
10811093
case ReferenceCounting::Block: \
10821094
case ReferenceCounting::Error: \
1095+
case ReferenceCounting::CxxCustom: \
10831096
case ReferenceCounting::None: \
10841097
llvm_unreachable("unsupported reference kind with reference storage"); \
10851098
} \
@@ -1097,6 +1110,7 @@ llvm::Type *IRGenModule::getReferenceType(ReferenceCounting refcounting) {
10971110
case ReferenceCounting::Bridge: \
10981111
case ReferenceCounting::Block: \
10991112
case ReferenceCounting::Error: \
1113+
case ReferenceCounting::CxxCustom: \
11001114
case ReferenceCounting::None: \
11011115
llvm_unreachable("unsupported reference kind with reference storage"); \
11021116
} \

lib/IRGen/GenObjC.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/IR/InlineAsm.h"
2222

2323
#include "clang/AST/ASTContext.h"
24+
#include "clang/AST/GlobalDecl.h"
2425
#include "clang/Basic/CharInfo.h"
2526
#include "clang/CodeGen/CGFunctionInfo.h"
2627

@@ -1520,3 +1521,16 @@ void IRGenFunction::emitBlockRelease(llvm::Value *value) {
15201521
auto call = Builder.CreateCall(fn, value);
15211522
call->setDoesNotThrow();
15221523
}
1524+
1525+
void IRGenFunction::emitForeignReferenceTypeLifetimeOperation(ValueDecl *fn, llvm::Value *value) {
1526+
assert(fn->getClangDecl() && isa<clang::FunctionDecl>(fn->getClangDecl()));
1527+
1528+
auto clangFn = cast<clang::FunctionDecl>(fn->getClangDecl());
1529+
auto llvmFn = IGM.getAddrOfClangGlobalDecl(clangFn, ForDefinition);
1530+
1531+
auto argType = cast<llvm::FunctionType>(llvmFn->getType()->getPointerElementType())->getParamType(0);
1532+
value = Builder.CreateBitCast(value, argType);
1533+
1534+
auto call = Builder.CreateCall(llvmFn, value);
1535+
call->setDoesNotThrow();
1536+
}

lib/IRGen/GenType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,7 @@ IRGenModule::getReferenceObjectTypeInfo(ReferenceCounting refcounting) {
16001600
case ReferenceCounting::Block:
16011601
case ReferenceCounting::Error:
16021602
case ReferenceCounting::ObjC:
1603+
case ReferenceCounting::CxxCustom:
16031604
case ReferenceCounting::None:
16041605
llvm_unreachable("not implemented");
16051606
}

lib/IRGen/GenValueWitness.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ getAddrOfKnownValueWitnessTable(IRGenModule &IGM, CanType type,
11631163
break;
11641164
case ReferenceCounting::Error:
11651165
case ReferenceCounting::None:
1166+
case ReferenceCounting::CxxCustom:
11661167
break;
11671168
}
11681169
}

0 commit comments

Comments
 (0)