Skip to content

Commit ee41f32

Browse files
authored
Merge pull request #63599 from hyp/eng/vtable4
[interop][SwiftToCxx] dispatch swift class methods using signed isa a…
2 parents f5488c5 + 981e828 commit ee41f32

7 files changed

+243
-77
lines changed

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,19 @@ class IRABIDetailsProvider {
258258
/// The call should be made via the provided thunk function.
259259
Thunk
260260
};
261+
struct PointerAuthDiscriminator {
262+
/// The value of the other discriminator
263+
uint64_t value;
264+
};
261265

262266
static MethodDispatchInfo direct() {
263267
return MethodDispatchInfo(Kind::Direct, 0);
264268
}
265269

266-
static MethodDispatchInfo indirectVTableStaticOffset(size_t bitOffset) {
267-
return MethodDispatchInfo(Kind::IndirectVTableStaticOffset, bitOffset);
270+
static MethodDispatchInfo indirectVTableStaticOffset(
271+
size_t bitOffset, Optional<PointerAuthDiscriminator> discriminator) {
272+
return MethodDispatchInfo(Kind::IndirectVTableStaticOffset, bitOffset, "",
273+
discriminator);
268274
}
269275

270276
static MethodDispatchInfo thunk(std::string thunkName) {
@@ -276,18 +282,25 @@ class IRABIDetailsProvider {
276282
assert(kind == Kind::IndirectVTableStaticOffset);
277283
return bitOffset;
278284
}
285+
Optional<PointerAuthDiscriminator> getPointerAuthDiscriminator() const {
286+
assert(kind == Kind::IndirectVTableStaticOffset);
287+
return discriminator;
288+
}
279289
StringRef getThunkSymbolName() const {
280290
assert(kind == Kind::Thunk);
281291
return thunkName;
282292
}
283293

284294
private:
285-
MethodDispatchInfo(Kind kind, size_t bitOffset, std::string thunkName = "")
286-
: kind(kind), bitOffset(bitOffset), thunkName(thunkName) {}
295+
MethodDispatchInfo(Kind kind, size_t bitOffset, std::string thunkName = "",
296+
Optional<PointerAuthDiscriminator> discriminator = None)
297+
: kind(kind), bitOffset(bitOffset), thunkName(thunkName),
298+
discriminator(discriminator) {}
287299

288300
Kind kind;
289301
size_t bitOffset;
290302
std::string thunkName;
303+
Optional<PointerAuthDiscriminator> discriminator;
291304
};
292305

293306
Optional<MethodDispatchInfo>

lib/IRGen/IRABIDetailsProvider.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "Callee.h"
1515
#include "FixedTypeInfo.h"
1616
#include "GenEnum.h"
17+
#include "GenPointerAuth.h"
1718
#include "GenType.h"
1819
#include "GenericRequirement.h"
1920
#include "IRGen.h"
@@ -206,6 +207,21 @@ class IRABIDetailsProviderImpl {
206207

207208
using MethodDispatchInfo = IRABIDetailsProvider::MethodDispatchInfo;
208209

210+
Optional<MethodDispatchInfo::PointerAuthDiscriminator>
211+
getMethodPointerAuthInfo(const AbstractFunctionDecl *funcDecl,
212+
SILDeclRef method) {
213+
// FIXME: Async support.
214+
if (funcDecl->hasAsync())
215+
return None;
216+
const auto &schema = IGM.getOptions().PointerAuth.SwiftClassMethods;
217+
if (!schema)
218+
return None;
219+
auto discriminator =
220+
PointerAuthInfo::getOtherDiscriminator(IGM, schema, method);
221+
return MethodDispatchInfo::PointerAuthDiscriminator{
222+
discriminator->getZExtValue()};
223+
}
224+
209225
Optional<MethodDispatchInfo>
210226
getMethodDispatchInfo(const AbstractFunctionDecl *funcDecl) {
211227
if (funcDecl->isSemanticallyFinal())
@@ -227,8 +243,8 @@ class IRABIDetailsProviderImpl {
227243
if (!isa<ClassMetadataLayout>(layout))
228244
return {};
229245
auto &classLayout = cast<ClassMetadataLayout>(layout);
230-
auto *mi = classLayout.getStoredMethodInfoIfPresent(
231-
SILDeclRef(const_cast<AbstractFunctionDecl *>(funcDecl)));
246+
auto silDecl = SILDeclRef(const_cast<AbstractFunctionDecl *>(funcDecl));
247+
auto *mi = classLayout.getStoredMethodInfoIfPresent(silDecl);
232248
if (!mi)
233249
return {};
234250
switch (mi->TheKind) {
@@ -237,7 +253,8 @@ class IRABIDetailsProviderImpl {
237253
case ClassMetadataLayout::MethodInfo::Kind::Offset:
238254
if (mi->TheOffset.isStatic()) {
239255
return MethodDispatchInfo::indirectVTableStaticOffset(
240-
/*bitOffset=*/mi->TheOffset.getStaticOffset().getValue());
256+
/*bitOffset=*/mi->TheOffset.getStaticOffset().getValue(),
257+
getMethodPointerAuthInfo(funcDecl, silDecl));
241258
}
242259
return {};
243260
}

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "PrintClangClassType.h"
1919
#include "PrintClangValueType.h"
2020
#include "SwiftToClangInteropContext.h"
21+
#include "swift/ABI/MetadataValues.h"
2122
#include "swift/AST/Decl.h"
2223
#include "swift/AST/GenericParamList.h"
2324
#include "swift/AST/Module.h"
@@ -1107,13 +1108,27 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
11071108
os << "void ***selfPtr_ = reinterpret_cast<void ***>( "
11081109
"::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));"
11091110
"\n";
1111+
1112+
os << "#ifdef __arm64e__\n";
1113+
os << "void **vtable_ = ptrauth_auth_data(*selfPtr_, "
1114+
"ptrauth_key_process_independent_data, "
1115+
"ptrauth_blend_discriminator(selfPtr_,"
1116+
<< SpecialPointerAuthDiscriminators::ObjCISA << "));\n";
1117+
os << "#else\n";
11101118
os << "void **vtable_ = *selfPtr_;\n";
1111-
os << "using FType = decltype("
1112-
<< cxx_synthesis::getCxxImplNamespaceName() << "::" << swiftSymbolName
1113-
<< ");\n";
1114-
os << "FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + "
1115-
<< (dispatchInfo->getStaticBitOffset() / 8) << "));\n";
1116-
indirectFunctionVar = StringRef("fptr_");
1119+
os << "#endif\n";
1120+
os << "struct FTypeAddress {\n";
1121+
os << "decltype(" << cxx_synthesis::getCxxImplNamespaceName()
1122+
<< "::" << swiftSymbolName << ") *";
1123+
if (auto ptrAuthDisc = dispatchInfo->getPointerAuthDiscriminator())
1124+
os << " __ptrauth_swift_class_method_pointer(" << ptrAuthDisc->value
1125+
<< ')';
1126+
os << " func;\n";
1127+
os << "};\n";
1128+
os << "FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ "
1129+
"+ "
1130+
<< (dispatchInfo->getStaticBitOffset() / 8) << ");\n";
1131+
indirectFunctionVar = StringRef("fptrptr_->func");
11171132
break;
11181133
case DispatchKindTy::Thunk:
11191134
swiftSymbolName = dispatchInfo->getThunkSymbolName();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %S/swift-class-virtual-method-dispatch.swift -target arm64e-apple-ios12.0 -typecheck -module-name Class -clang-header-expose-decls=all-public -emit-clang-header-path %t/class.h
3+
// RUN: %FileCheck %s < %t/class.h
4+
5+
// RUN: %check-interop-cxx-header-in-clang(%t/class.h)
6+
7+
// REQUIRES: CPU=arm64e
8+
// REQUIRES: OS=ios
9+
10+
// note: uses swift-class-virtual-method-dispatch.swift
11+
12+
// CHECK: void BaseClass::virtualMethod() {
13+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
14+
// CHECK-NEXT: #ifdef __arm64e__
15+
// CHECK-NEXT: void **vtable_ = ptrauth_auth_data(*selfPtr_, ptrauth_key_process_independent_data, ptrauth_blend_discriminator(selfPtr_,27361));
16+
// CHECK-NEXT: #else
17+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
18+
// CHECK-NEXT: #endif
19+
// CHECK-NEXT: struct FTypeAddress {
20+
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C13virtualMethodyyF) * __ptrauth_swift_class_method_pointer([[#AUTH:]]) func;
21+
// CHECK-NEXT: };
22+
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM1:]]);
23+
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
24+
// CHECK-NEXT: }

test/Interop/SwiftToCxx/class/swift-class-virtual-method-dispatch-execution.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
// RUN: %target-codesign %t/swift-class-execution
99
// RUN: %target-run %t/swift-class-execution | %FileCheck %s
1010

11-
// FIXME: pointer signing support.
12-
// UNSUPPORTED: CPU=arm64e
13-
1411
// REQUIRES: executable_test
1512

1613
#include "class.h"

0 commit comments

Comments
 (0)