Skip to content

Commit 53ab3ef

Browse files
authored
Merge pull request #34993 from zoecarver/cxx/cxxmethod-representation
[cxx-interop] Add SIL function representation cxx_method; Support extending C++ types.
2 parents bebe119 + 036361d commit 53ab3ef

37 files changed

+370
-102
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,8 @@ Types
591591
FUNCTION-KIND ::= 'B' // objc block function type
592592
FUNCTION-KIND ::= 'zB' C-TYPE // objc block type with non-canonical C type
593593
FUNCTION-KIND ::= 'L' // objc block function type with canonical C type (escaping) (DWARF only; otherwise use 'B' or 'zB' C-TYPE)
594-
FUNCTION-KIND ::= 'C' // C function pointer type
595-
FUNCTION-KIND ::= 'zC' C-TYPE // C function pointer type with with non-canonical C type
594+
FUNCTION-KIND ::= 'C' // C function pointer / C++ method type
595+
FUNCTION-KIND ::= 'zC' C-TYPE // C function pointer / C++ method type with with non-canonical C type
596596
FUNCTION-KIND ::= 'A' // @auto_closure function type (escaping)
597597
FUNCTION-KIND ::= 'E' // function type (noescape)
598598

include/swift/AST/ExtInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ enum class SILFunctionTypeRepresentation : uint8_t {
167167

168168
/// A closure invocation function that has not been bound to a context.
169169
Closure,
170+
171+
/// A C++ method that takes a "this" argument (not a static C++ method or
172+
/// constructor). Except for
173+
/// handling the "this" argument, has the same behavior as "CFunctionPointer".
174+
CXXMethod,
170175
};
171176

172177
/// Returns true if the function with this convention doesn't carry a context.
@@ -196,6 +201,7 @@ isThinRepresentation(SILFunctionTypeRepresentation rep) {
196201
case SILFunctionTypeRepresentation::WitnessMethod:
197202
case SILFunctionTypeRepresentation::CFunctionPointer:
198203
case SILFunctionTypeRepresentation::Closure:
204+
case SILFunctionTypeRepresentation::CXXMethod:
199205
return true;
200206
}
201207
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
@@ -232,6 +238,7 @@ convertRepresentation(SILFunctionTypeRepresentation rep) {
232238
return {FunctionTypeRepresentation::Block};
233239
case SILFunctionTypeRepresentation::Thin:
234240
return {FunctionTypeRepresentation::Thin};
241+
case SILFunctionTypeRepresentation::CXXMethod:
235242
case SILFunctionTypeRepresentation::CFunctionPointer:
236243
return {FunctionTypeRepresentation::CFunctionPointer};
237244
case SILFunctionTypeRepresentation::Method:
@@ -252,6 +259,7 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
252259
case SILFunctionTypeRepresentation::CFunctionPointer:
253260
case SILFunctionTypeRepresentation::Block:
254261
case SILFunctionTypeRepresentation::Closure:
262+
case SILFunctionTypeRepresentation::CXXMethod:
255263
return false;
256264
case SILFunctionTypeRepresentation::ObjCMethod:
257265
case SILFunctionTypeRepresentation::Method:
@@ -269,6 +277,7 @@ template <typename Repr> constexpr bool shouldStoreClangType(Repr repr) {
269277
switch (static_cast<SILFunctionTypeRepresentation>(repr)) {
270278
case SILFunctionTypeRepresentation::CFunctionPointer:
271279
case SILFunctionTypeRepresentation::Block:
280+
case SILFunctionTypeRepresentation::CXXMethod:
272281
return true;
273282
case SILFunctionTypeRepresentation::ObjCMethod:
274283
case SILFunctionTypeRepresentation::Thick:
@@ -392,6 +401,7 @@ class ASTExtInfoBuilder {
392401
case SILFunctionTypeRepresentation::ObjCMethod:
393402
case SILFunctionTypeRepresentation::Method:
394403
case SILFunctionTypeRepresentation::WitnessMethod:
404+
case SILFunctionTypeRepresentation::CXXMethod:
395405
return true;
396406
}
397407
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
@@ -618,6 +628,7 @@ SILFunctionLanguage getSILFunctionLanguage(SILFunctionTypeRepresentation rep) {
618628
case SILFunctionTypeRepresentation::ObjCMethod:
619629
case SILFunctionTypeRepresentation::CFunctionPointer:
620630
case SILFunctionTypeRepresentation::Block:
631+
case SILFunctionTypeRepresentation::CXXMethod:
621632
return SILFunctionLanguage::C;
622633
case SILFunctionTypeRepresentation::Thick:
623634
case SILFunctionTypeRepresentation::Thin:
@@ -750,6 +761,7 @@ class SILExtInfoBuilder {
750761
case Representation::ObjCMethod:
751762
case Representation::Method:
752763
case Representation::WitnessMethod:
764+
case SILFunctionTypeRepresentation::CXXMethod:
753765
return true;
754766
}
755767
llvm_unreachable("Unhandled Representation in switch.");
@@ -767,6 +779,7 @@ class SILExtInfoBuilder {
767779
case Representation::Method:
768780
case Representation::WitnessMethod:
769781
case Representation::Closure:
782+
case SILFunctionTypeRepresentation::CXXMethod:
770783
return false;
771784
}
772785
llvm_unreachable("Unhandled Representation in switch.");

include/swift/SIL/ApplySite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ class ApplySite {
237237
bool isCalleeThin() const {
238238
switch (getSubstCalleeType()->getRepresentation()) {
239239
case SILFunctionTypeRepresentation::CFunctionPointer:
240+
case SILFunctionTypeRepresentation::CXXMethod:
240241
case SILFunctionTypeRepresentation::Thin:
241242
case SILFunctionTypeRepresentation::Method:
242243
case SILFunctionTypeRepresentation::ObjCMethod:

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ getSILFunctionTypeRepresentationString(SILFunctionType::Representation value) {
129129
case SILFunctionType::Representation::Thick: return "thick";
130130
case SILFunctionType::Representation::Block: return "block";
131131
case SILFunctionType::Representation::CFunctionPointer: return "c";
132+
case SILFunctionType::Representation::CXXMethod:
133+
return "cxx_method";
132134
case SILFunctionType::Representation::Thin: return "thin";
133135
case SILFunctionType::Representation::Method: return "method";
134136
case SILFunctionType::Representation::ObjCMethod: return "objc_method";

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,7 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
18451845
OpArgs.push_back('B');
18461846
appendClangTypeToVec(OpArgs);
18471847
break;
1848+
case SILFunctionTypeRepresentation::CXXMethod:
18481849
case SILFunctionTypeRepresentation::CFunctionPointer:
18491850
if (!mangleClangType) {
18501851
OpArgs.push_back('C');

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4886,6 +4886,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
48864886
case SILFunctionType::Representation::Method:
48874887
Printer << "method";
48884888
break;
4889+
case SILFunctionType::Representation::CXXMethod:
4890+
Printer << "cxx_method";
4891+
break;
48894892
case SILFunctionType::Representation::ObjCMethod:
48904893
Printer << "objc_method";
48914894
break;
@@ -4964,6 +4967,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
49644967
case SILFunctionType::Representation::Method:
49654968
Printer << "method";
49664969
break;
4970+
case SILFunctionType::Representation::CXXMethod:
4971+
Printer << "cxx_method";
4972+
break;
49674973
case SILFunctionType::Representation::ObjCMethod:
49684974
Printer << "objc_method";
49694975
break;

lib/AST/ClangTypeConverter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ const clang::Type *ClangTypeConverter::getFunctionType(
212212
return nullptr;
213213

214214
switch (repr) {
215+
case SILFunctionType::Representation::CXXMethod:
215216
case SILFunctionType::Representation::CFunctionPointer:
216217
return ClangASTContext.getPointerType(fn).getTypePtr();
217218
case SILFunctionType::Representation::Block:

lib/AST/ExtInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Optional<UnexpectedClangTypeError> UnexpectedClangTypeError::checkClangType(
6868
#else
6969
bool isBlock = true;
7070
switch (silRep) {
71+
case SILFunctionTypeRepresentation::CXXMethod:
7172
case SILFunctionTypeRepresentation::CFunctionPointer:
7273
isBlock = false;
7374
LLVM_FALLTHROUGH;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4085,18 +4085,20 @@ namespace {
40854085
templateParams);
40864086

40874087
if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
4088+
// Subscripts and call operators are imported as normal methods.
4089+
bool staticOperator = mdecl->isOverloadedOperator() &&
4090+
mdecl->getOverloadedOperator() != clang::OO_Call &&
4091+
mdecl->getOverloadedOperator() != clang::OO_Subscript;
40884092
if (mdecl->isStatic() ||
40894093
// C++ operators that are implemented as non-static member
40904094
// functions get imported into Swift as static member functions
40914095
// that use an additional parameter for the left-hand side operand
40924096
// instead of the receiver object.
4093-
(mdecl->getDeclName().getNameKind() ==
4094-
clang::DeclarationName::CXXOperatorName &&
4095-
isImportedAsStatic(mdecl->getOverloadedOperator()))) {
4097+
staticOperator) {
40964098
selfIdx = None;
40974099
} else {
4098-
selfIdx = 0;
4099-
// Don't import members of a class decl as mutating.
4100+
// Swift imports the "self" param last, even for clang functions.
4101+
selfIdx = bodyParams ? bodyParams->size() : 0;
41004102
// If the method is imported as mutating, this implicitly makes the
41014103
// parameter indirect.
41024104
selfIsInOut =

lib/ClangImporter/ImportType.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1897,7 +1897,11 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
18971897
// imported into Swift as static methods that have an additional
18981898
// parameter for the left-hand side operand instead of the receiver object.
18991899
if (auto CMD = dyn_cast<clang::CXXMethodDecl>(clangDecl)) {
1900-
if (clangDecl->isOverloadedOperator() && isImportedAsStatic(clangDecl->getOverloadedOperator())) {
1900+
// Subscripts and call operators are imported as normal methods.
1901+
bool staticOperator = clangDecl->isOverloadedOperator() &&
1902+
clangDecl->getOverloadedOperator() != clang::OO_Call &&
1903+
clangDecl->getOverloadedOperator() != clang::OO_Subscript;
1904+
if (staticOperator) {
19011905
auto param = new (SwiftContext)
19021906
ParamDecl(SourceLoc(), SourceLoc(), Identifier(), SourceLoc(),
19031907
SwiftContext.getIdentifier("lhs"), dc);

lib/IRGen/Callee.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,9 @@ namespace irgen {
462462
/// Given that this callee is a block, return the block pointer.
463463
llvm::Value *getBlockObject() const;
464464

465+
/// Given that this callee is a C++ method, return the self argument.
466+
llvm::Value *getCXXMethodSelf() const;
467+
465468
/// Given that this callee is an ObjC method, return the receiver
466469
/// argument. This might not be 'self' anymore.
467470
llvm::Value *getObjCMethodReceiver() const;

lib/IRGen/GenCall.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ llvm::CallingConv::ID irgen::expandCallingConv(IRGenModule &IGM,
293293
switch (convention) {
294294
case SILFunctionTypeRepresentation::CFunctionPointer:
295295
case SILFunctionTypeRepresentation::ObjCMethod:
296+
case SILFunctionTypeRepresentation::CXXMethod:
296297
case SILFunctionTypeRepresentation::Block:
297298
return llvm::CallingConv::C;
298299

@@ -1326,6 +1327,7 @@ void SignatureExpansion::expandExternalSignatureTypes() {
13261327
paramTys.push_back(clangCtx.VoidPtrTy);
13271328
break;
13281329

1330+
case SILFunctionTypeRepresentation::CXXMethod:
13291331
case SILFunctionTypeRepresentation::CFunctionPointer:
13301332
// No implicit arguments.
13311333
break;
@@ -1642,6 +1644,7 @@ void SignatureExpansion::expandParameters() {
16421644
case SILFunctionType::Representation::Method:
16431645
case SILFunctionType::Representation::WitnessMethod:
16441646
case SILFunctionType::Representation::ObjCMethod:
1647+
case SILFunctionType::Representation::CXXMethod:
16451648
case SILFunctionType::Representation::Thin:
16461649
case SILFunctionType::Representation::Closure:
16471650
return FnType->hasErrorResult();
@@ -1809,6 +1812,7 @@ void SignatureExpansion::expandAsyncEntryType() {
18091812
case SILFunctionType::Representation::ObjCMethod:
18101813
case SILFunctionType::Representation::Thin:
18111814
case SILFunctionType::Representation::Closure:
1815+
case SILFunctionType::Representation::CXXMethod:
18121816
return false;
18131817

18141818
case SILFunctionType::Representation::Thick:
@@ -2203,7 +2207,20 @@ class SyncCallEmission final : public CallEmission {
22032207
break;
22042208

22052209
case SILFunctionTypeRepresentation::Block:
2206-
adjusted.add(getCallee().getBlockObject());
2210+
case SILFunctionTypeRepresentation::CXXMethod:
2211+
if (getCallee().getRepresentation() == SILFunctionTypeRepresentation::Block) {
2212+
adjusted.add(getCallee().getBlockObject());
2213+
} else {
2214+
auto selfParam = origCalleeType->getSelfParameter();
2215+
auto *arg = getCallee().getCXXMethodSelf();
2216+
// We might need to fix the level of indirection for foreign reference types.
2217+
if (selfParam.getInterfaceType().isForeignReferenceType() &&
2218+
isIndirectFormalParameter(selfParam.getConvention()))
2219+
arg = IGF.Builder.CreateLoad(arg, IGF.IGM.getPointerAlignment());
2220+
2221+
adjusted.add(arg);
2222+
}
2223+
22072224
LLVM_FALLTHROUGH;
22082225

22092226
case SILFunctionTypeRepresentation::CFunctionPointer:
@@ -2462,14 +2479,9 @@ class AsyncCallEmission final : public CallEmission {
24622479
// Translate the formal arguments and handle any special arguments.
24632480
switch (getCallee().getRepresentation()) {
24642481
case SILFunctionTypeRepresentation::ObjCMethod:
2465-
assert(false && "Should not reach this");
2466-
break;
2467-
24682482
case SILFunctionTypeRepresentation::Block:
2469-
assert(false && "Should not reach this");
2470-
break;
2471-
24722483
case SILFunctionTypeRepresentation::CFunctionPointer:
2484+
case SILFunctionTypeRepresentation::CXXMethod:
24732485
assert(false && "Should not reach this");
24742486
break;
24752487

@@ -3148,6 +3160,9 @@ Callee::Callee(CalleeInfo &&info, const FunctionPointer &fn,
31483160
case SILFunctionTypeRepresentation::CFunctionPointer:
31493161
assert(!FirstData && !SecondData);
31503162
break;
3163+
case SILFunctionTypeRepresentation::CXXMethod:
3164+
assert(FirstData && !SecondData);
3165+
break;
31513166
}
31523167
#endif
31533168

@@ -3160,6 +3175,7 @@ llvm::Value *Callee::getSwiftContext() const {
31603175
case SILFunctionTypeRepresentation::CFunctionPointer:
31613176
case SILFunctionTypeRepresentation::Thin:
31623177
case SILFunctionTypeRepresentation::Closure:
3178+
case SILFunctionTypeRepresentation::CXXMethod:
31633179
return nullptr;
31643180

31653181
case SILFunctionTypeRepresentation::WitnessMethod:
@@ -3182,6 +3198,14 @@ llvm::Value *Callee::getBlockObject() const {
31823198
return FirstData;
31833199
}
31843200

3201+
llvm::Value *Callee::getCXXMethodSelf() const {
3202+
assert(Info.OrigFnType->getRepresentation() ==
3203+
SILFunctionTypeRepresentation::CXXMethod &&
3204+
"not a C++ method");
3205+
assert(FirstData && "no self object set on callee");
3206+
return FirstData;
3207+
}
3208+
31853209
llvm::Value *Callee::getObjCMethodReceiver() const {
31863210
assert(Info.OrigFnType->getRepresentation() ==
31873211
SILFunctionTypeRepresentation::ObjCMethod &&
@@ -3496,6 +3520,7 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
34963520
// The index of the first "physical" parameter from paramTys/FI that
34973521
// corresponds to a logical parameter from params.
34983522
unsigned firstParam = 0;
3523+
unsigned paramEnd = FI.arg_size();
34993524

35003525
// Handle the ObjC prefix.
35013526
if (callee.getRepresentation() == SILFunctionTypeRepresentation::ObjCMethod) {
@@ -3509,14 +3534,19 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
35093534
== SILFunctionTypeRepresentation::Block) {
35103535
// Ignore the physical block-object parameter.
35113536
firstParam += 1;
3512-
// Or the indirect result parameter.
3513-
} else if (fnType->getNumResults() > 0 &&
3537+
} else if (callee.getRepresentation() ==
3538+
SILFunctionTypeRepresentation::CXXMethod) {
3539+
// Skip the "self" param.
3540+
paramEnd--;
3541+
}
3542+
3543+
if (fnType->getNumResults() > 0 &&
35143544
fnType->getSingleResult().isFormalIndirect()) {
35153545
// Ignore the indirect result parameter.
35163546
firstParam += 1;
35173547
}
35183548

3519-
for (unsigned i = firstParam, e = FI.arg_size(); i != e; ++i) {
3549+
for (unsigned i = firstParam; i != paramEnd; ++i) {
35203550
auto clangParamTy = FI.arg_begin()[i].type;
35213551
auto &AI = FI.arg_begin()[i].info;
35223552

lib/IRGen/GenFunc.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ const TypeInfo *TypeConverter::convertFunctionType(SILFunctionType *T) {
528528

529529
case SILFunctionType::Representation::Thin:
530530
case SILFunctionType::Representation::Method:
531+
case SILFunctionType::Representation::CXXMethod:
531532
case SILFunctionType::Representation::WitnessMethod:
532533
case SILFunctionType::Representation::ObjCMethod:
533534
case SILFunctionType::Representation::CFunctionPointer:
@@ -583,6 +584,7 @@ getFuncSignatureInfoForLowered(IRGenModule &IGM, CanSILFunctionType type) {
583584
case SILFunctionType::Representation::Thin:
584585
case SILFunctionType::Representation::CFunctionPointer:
585586
case SILFunctionType::Representation::Method:
587+
case SILFunctionType::Representation::CXXMethod:
586588
case SILFunctionType::Representation::WitnessMethod:
587589
case SILFunctionType::Representation::ObjCMethod:
588590
case SILFunctionType::Representation::Closure:

lib/IRGen/GenPointerAuth.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ static const PointerAuthSchema &getFunctionPointerSchema(IRGenModule &IGM,
190190
CanSILFunctionType fnType) {
191191
auto &options = IGM.getOptions().PointerAuth;
192192
switch (fnType->getRepresentation()) {
193+
case SILFunctionTypeRepresentation::CXXMethod:
193194
case SILFunctionTypeRepresentation::CFunctionPointer:
194195
return options.FunctionPointers;
195196

@@ -583,6 +584,7 @@ PointerAuthEntity::getTypeDiscriminator(IRGenModule &IGM) const {
583584
}
584585

585586
// C function pointers are undiscriminated.
587+
case SILFunctionTypeRepresentation::CXXMethod:
586588
case SILFunctionTypeRepresentation::CFunctionPointer:
587589
return llvm::ConstantInt::get(IGM.Int64Ty, 0);
588590

lib/IRGen/GenProto.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,6 +2321,7 @@ bool irgen::hasPolymorphicParameters(CanSILFunctionType ty) {
23212321

23222322
case SILFunctionTypeRepresentation::CFunctionPointer:
23232323
case SILFunctionTypeRepresentation::ObjCMethod:
2324+
case SILFunctionTypeRepresentation::CXXMethod:
23242325
// May be polymorphic at the SIL level, but no type metadata is actually
23252326
// passed.
23262327
return false;

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2930,6 +2930,7 @@ Callee LoweredValue::getCallee(IRGenFunction &IGF,
29302930
return getBlockPointerCallee(IGF, functionValue, std::move(calleeInfo));
29312931

29322932
case SILFunctionType::Representation::ObjCMethod:
2933+
case SILFunctionType::Representation::CXXMethod:
29332934
case SILFunctionType::Representation::Thick:
29342935
llvm_unreachable("unexpected function with singleton representation");
29352936

@@ -2991,6 +2992,7 @@ static std::unique_ptr<CallEmission> getCallEmissionForLoweredValue(
29912992
}
29922993

29932994
case SILFunctionType::Representation::ObjCMethod:
2995+
case SILFunctionType::Representation::CXXMethod:
29942996
case SILFunctionType::Representation::Thick:
29952997
case SILFunctionType::Representation::Block:
29962998
case SILFunctionType::Representation::Thin:
@@ -3363,6 +3365,7 @@ getPartialApplicationFunction(IRGenSILFunction &IGF, SILValue v,
33633365
case SILFunctionTypeRepresentation::CFunctionPointer:
33643366
case SILFunctionTypeRepresentation::Block:
33653367
case SILFunctionTypeRepresentation::ObjCMethod:
3368+
case SILFunctionTypeRepresentation::CXXMethod:
33663369
llvm_unreachable("partial_apply of foreign functions not implemented");
33673370

33683371
case SILFunctionTypeRepresentation::WitnessMethod:

0 commit comments

Comments
 (0)