Skip to content

Commit 036361d

Browse files
committed
[cxx-interop] Add SIL function representation cxx_method; Support extending C++ types.
There are three major changes here: 1. The addition of "SILFunctionTypeRepresentation::CXXMethod". 2. C++ methods are imported with their members *last*. Then the arguments are switched when emitting the IR for an application of the function. 3. Clang decls are now marked as foreign witnesses. These are all steps towards being able to have C++ protocol conformance.
1 parent 2928459 commit 036361d

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
@@ -1828,6 +1828,7 @@ void ASTMangler::appendImplFunctionType(SILFunctionType *fn,
18281828
OpArgs.push_back('B');
18291829
appendClangTypeToVec(OpArgs);
18301830
break;
1831+
case SILFunctionTypeRepresentation::CXXMethod:
18311832
case SILFunctionTypeRepresentation::CFunctionPointer:
18321833
if (!mangleClangType) {
18331834
OpArgs.push_back('C');

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4885,6 +4885,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
48854885
case SILFunctionType::Representation::Method:
48864886
Printer << "method";
48874887
break;
4888+
case SILFunctionType::Representation::CXXMethod:
4889+
Printer << "cxx_method";
4890+
break;
48884891
case SILFunctionType::Representation::ObjCMethod:
48894892
Printer << "objc_method";
48904893
break;
@@ -4963,6 +4966,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
49634966
case SILFunctionType::Representation::Method:
49644967
Printer << "method";
49654968
break;
4969+
case SILFunctionType::Representation::CXXMethod:
4970+
Printer << "cxx_method";
4971+
break;
49664972
case SILFunctionType::Representation::ObjCMethod:
49674973
Printer << "objc_method";
49684974
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);

0 commit comments

Comments
 (0)